sizeof struct sehr seltsam...



  • Hi!

    Ich bin gerade dabei, mysteriöse Files relativ komplexen Datenstrukturen einzulesen und in eine DB zu schreiben. Mein Verständnisproblem ist, dass ich von meinem Auftraggeber eine header-Datei bekommen habe, die auf den ersten Blick nicht zu den import-Dateien passt, aber durch seltsame Effekte doch zum gewünschten Ergebnis führt: Folgende struct hat eine sizeof() von 20 Byte!

    typedef unsigned int u32;
    typedef unsigned short int u16;
    typedef unsigned char u8;
    typedef signed short int s16;
    
    typedef struct  {
      u32 serialNumber;							// serial number of the unit
      u8  formatVersion;							// indicates the format type, first revision : 1
      u32 securitykey;								// ?
      u16 startIndex;								// first index ID of this data block (queue ID¥s 0...65535)
      u16 IDsinBlock;								// data entries in this data block
      u16 checksum;  					    		// simple checksum over all following data entries ( add all UINT16 values )
    } DLheader;   // size: 15 byte !? 20???
    

    Ich zähle 15! hinter der format Version sind drei bytes genullt in den Importdateien. Auf "magische Weise" scheint das mein compiler zu wissen...
    Wahrscheinlich gibt es eine simple Regel, aufgrund derer der ganze quatsch passiert. Kann mir jemand weiterhelfen?

    Viele Grüße
    Sören



  • typedef struct  { 
    //-------------------------------
      u32 serialNumber;    //       4
    //-------------------------------
      u8  formatVersion;   //   1
    pad1                   // + 3 = 4
    //-------------------------------
      u32 securitykey;     //       4
    //-------------------------------
      u16 startIndex;      //   2
      u16 IDsinBlock;      // + 2 = 4
    //-------------------------------
      u16 checksum;        //   2
    pad2                   // + 2 = 4
    //-------------------------------
    } DLheader;
    


  • Stichworte alignment, padding



  • typedef struct  {
      u32 serialNumber;
      u32 securitykey;
      u16 startIndex;
      u16 IDsinBlock;
      u16 checksum;
      u8  formatVersion;
    }
    

    Und dieses struct ist 16 Bytes bei mir gross. Ich schaetze, dass es vom Compiler und vom System abhaengig ist. Ich wuerde keine struct einfach unformatiert in eine Datei schreiben und wieder herauslesen.



  • Ok, hab die Regel gefunden:

    Scheinbar aligned der Compiler die Daten so, dass ein u32 nicht an Stelle 7 anfangen kann(also nur durch 4 Teilbar). Entsprechend mit u16.

    Cheers
    Sören



  • soerenP schrieb:

    Wahrscheinlich gibt es eine simple Regel, aufgrund derer der ganze quatsch passiert.

    naja, speicherzugriffe sollen möglichst schnell gehen und der code soll klein werden, deswegen werden füllbytes eingefügt. das kannste ihm aber abgewöhnen, versuch mal: #pragma pack(1) (oder #pragma align 1, oder wie dein compiler sowas macht), dann sollten keine löcher mehr entstehen (dafür kann der code aber langsamer und grösser werden).
    🙂



  • Oha 😉

    Hey, danke!

    Hab es jetzt manuell gepaddet, damit es unabhängiger vom Compiler ist. Schreiben tut die Datei leider jemand anders (Stichwort: Vooodoooo)...

    Und um gottes Willen kein pragma pack. 😉
    Es hat doch funktioniert, ich hab mich nur gefragt, warum.

    Danke nochmal
    Sören



  • soerenP schrieb:

    Hab es jetzt manuell gepaddet, damit es unabhängiger vom Compiler ist. Schreiben tut die Datei leider jemand anders (Stichwort: Vooodoooo)...

    Und um gottes Willen kein pragma pack. 😉
    Sören

    Ja, hat böse Seiten auch, so ein pragma. Aber eigentlich ist es meist einen Versuch wert, unterschiedliches Verhalten damit zurechtzubiegen. Macro dokumentieren und gut ist es.

    Wenn Du selber padden willst, ist ein Header sinnvoll, der definiert, wie das Zeug sortiert ist (kannste jetzt ja nicht, weil Vodooherkunft). Es ist dann zwar möglich, eine bessere Kompatibilität herzustellen, aber Du bezahlst es oft mit einem Geschwindigkeitsverlust, der echt happig sein kann, wenn Du alles per fgetc() herzupfst. Little/BigEndian und ein paar andere Sachen stellen genügend Fallstricke bereit, um die Du Dich dann alle selber kümmern mußt.



  • soerenP schrieb:

    Oha 😉
    Schreiben tut die Datei leider jemand anders (Stichwort: Vooodoooo)...

    Was fürn Vieh?



  • soerenP schrieb:

    Und um gottes Willen kein pragma pack.

    ja, du hast recht, damit sollte man nicht zu leichtfertig sein. es gibt sogar beliebte betriebssysteme, die z.b. strukturen zusammenstauchen, und zusätzlich noch ganz abgefahrene compiler-extensions benutzen: (#define __bitwise__ __attribute__((bitwise))), nur damit's der programmierer bequem hat *fg* und seine structs auch direkt übers netz schicken kann. mit sowas nagelt man sich auf einen bestimmten compiler fest und zwingt ihn, miesen code zu erzeugen.
    🙂


Anmelden zum Antworten