Alignment Probleme



  • Hallo zusammen,

    ich Programmiere gerade ein Keil Board mit einem Arm7 MicroController (LPC2418). Nur habe ich jetzt eine Verständnisfrage. Und zwar habe ich folgende Structs und Definitionen:

    typedef struct
    {
      UInt  uiLength;    /* Current length of flex string */
      Char  charData[8]; /* Content of string */
    } FlexString8;
    
    typedef struct
    {
      FlexString8  Name;    
      FlexString4  Version; 
    } DeviceIdent_Struct;
    
    USInt usiOffset1 = offsetof ( DeviceIdent_Struct, Version ); // 0x0C     
    USInt usiOffset2 = offsetof ( FlexString8, charData ); // 0x02
    USInt usiOffset3 = sizeof(FlexString8); // 0x0C
    USInt usiOffset4 = sizeof(UInt); // 0x02
    USInt usiOffset5 = sizeof(Char); // 0x01
    USInt usiOffset6 = sizeof(Char[8]); // 0x08
    

    Nur weiss ich jetzt zb.B. leider nicht, wie die sizeOf( FlexString) zustande kommt. Eigentlich müsste die doch 10 sein und nicht 12. Liegt das am Alignment des Controllers?

    Unter welchen Umständen schmeisst der mir noch 2 "Füllbytes" in die Länge mir rein?

    Grü0e Nils



  • Habe übrigens einen arm-hitex-elf-gcc Compiler



  • Das Alignment liegt afaik im Ermessen des Compilers - und der richtet Strukturelemente normalerweise so aus, daß sie an Speicher-Positionen landen, die durch 2 oder 4 teilbar sind (weil da die Adressierung und Berechnung schneller ist).

    PS: Und viele Compiler dürften auch Möglichkeiten bieten, das Verhalten anzupassen, z.B. #pragma pack(...) beim MSVC.



  • Nils_Langner schrieb:

    typedef struct
    {
      UInt  uiLength;    /* Current length of flex string */
      Char  charData[8]; /* Content of string */
    } FlexString8;
    

    hi,
    die arms haben ja 'nen 32 bit core.
    deshalb nehme ich an, dass der für 'uiLength' 4 bytes belegt (sizeof(uint)+2 füllbytes), damit 'charData' an einer durch 4 teilbaren adresse landet..

    CStoll schrieb:

    PS: Und viele Compiler dürften auch Möglichkeiten bieten, das Verhalten anzupassen, z.B. #pragma pack(...) beim MSVC.

    beim keil sind das:
    #pragma pack(1) -> structs ohne lücken anlegen
    #pragma BYTEALIGN -> compiler soll code erzeugen um auf 'misaligned' daten zugreifen zu können

    beim gcc:
    __attribute__((packed)) am ende der struct definition
    beispiel:

    struct blabla
    {
      uint8 a;
      uint32 b;
    } __attribute__((packed));
    

    dann ergibt 'sizeof(struct blabla)' immer 5

    btw: wenn die füllbytes nicht weiter stören würde ich's aber so lassen. wenn man auf bytegrenzen packt, kann das programm u.u. gross und langsam werden...



  • @CStoll

    Aber wenn er immer 4 Bytes nehmen sollte, dann müsste doch

    USInt usiOffset2 = offsetof ( FlexString8, charData );
    

    4 sein und nicht 2 oder? Nach welchen Kriterien weiss ich denn, ob ich jetzt Füllbytes habe oder nicht?



  • Nils_Langner schrieb:

    Nach welchen Kriterien weiss ich denn, ob ich jetzt Füllbytes habe oder nicht?

    wenn die summe der sizeof()s aller struct member kleiner ist, als ein sizeof() der ganzen struct...



  • @net Ok, das war ja irgendwie klar, aber warum füllt er mir beim dem einen struct mit füllbytes auf und beim anderen nicht?



  • Nils_Langner schrieb:

    @net Ok, das war ja irgendwie klar, aber warum füllt er mir beim dem einen struct mit füllbytes auf und beim anderen nicht?

    bei der ersten struct hast du 2 bytes und 8 bytes. das sind zusammen 10 bytes. 10 ist aber nicht durch 4 ohne rest teilbar, also nimmt er das nächst höhere: 12
    bei der zweiten struct haste dann 12 und 12 bytes. weil die grösse beider member sowieso durch 4 teilbar ist, ist die summe auch durch 4 teilbar, also muss da nix mehr angehängt werden...



  • Wenn ich mir also diese zwei Werte anseh:

    USInt usiOffset2 = offsetof ( FlexString8, charData ); // 0x02 
    USInt usiOffset3 = sizeof(FlexString8); // 0x0C
    

    Dann müsste das im Speicher doch so aussehen:

    1        2         3        ... 10          11          12
    
    uiLength uiLength  charData ... charData    FüllByte    Füllbyte
    

    Wieso macht er mir die Füllbytes nicht nach uiLength, das würde doch charData an eine durch 4 teilbare Stelle schieben und es wäre schneller. Oder verstehe ich da was nicht?



  • Nils_Langner schrieb:

    Wieso macht er mir die Füllbytes nicht nach uiLength, das würde doch charData an eine durch 4 teilbare Stelle schieben und es wäre schneller. Oder verstehe ich da was nicht?

    naja, bei dem 'chardata' feld geht der compiler davon aus, dass du sowieso byteweise drauf zugreifen willst d.h. dieses feld an eine durch 4 teilbare adresse zu bringen würde nichts helfen. ich schätze mal, dass er die füllbyte an's ende packt, damit der zugriff auf nachfolgende variablen im speicher immer 4-aligned ist (so wie in deinem fall mit der struct mit den beiden 'FlexStrings'.


Anmelden zum Antworten