Speicherformat von structs



  • Hallo C/C++-Gemeinde,

    ich habe eine Frage was die Speicherung von structs im Speicher angeht.
    Folgender Code dient als Vorlage:

    #include <stdio.h>
    
    typedef unsigned int u32;
    
    struct date
    {
    	int year  : 23; // Jahr  (-4.194.304 bis 4.194.303)
    	u32 month : 4;  // Monat (1 bis 12)
    	u32 day   : 5;  // Tag   (1 bis 31)
    };
    
    int main(void)
    {
    	date.day = date.month = 4;
    	date.year = 2011;
    
    	printf("%x\n\n", date);
    }
    

    Wenn ich das Programm jetzt starte gibt er mir den Wert "210007db" als hexadezimale Wert aus.
    Kann mir einer von euch erklären wie es zu diesem Wert kommt.

    Ich dachte eigentlich, dass folgendes rauskommt:

    year  = 2011 -> 0000 0000 0001 1111 0110 11 (22 Bit)
    month =    4 ->                            00 100 (5 Bit)
    day   =    4 ->                                  0 0100 (5 Bit)
    
    -> 00 1f 6c 84
    

    Könnt ihr mir erklären wieso mein Gedankenvorgang hier nicht korrekt ist und wieso der Wert wie oben genannt gespeichert wird?

    mfg
    C Beginner


  • Mod

    Die interne Darstellung ist, wie immer, nicht fest definiert, selbst wenn man Bitfelder benutzt. Eventuell bietet dein Compiler spezielle Flags zum Feintuning an, wenn du etwas bestimmtes erreichen möchtest.

    Ein paar Stichworte, warum da etwas anderes rauskommt, als du erwartest: Padding, Endianess.
    Ich mag jetzt aber nicht im Details nachvollziehen, wie dein bestimmter Wert zustande kommt. Ist das wichtig?



  • year  = 2011 ->              00 0000 0000 0111 1101 1011 (22 Bit)
    month =    4 ->        001 00 (5 Bit)
    day   =    4 ->  0010 0 (5 Bit)
    

    Liegt wohl an der Endianes.



  • Also an den Endians kann's meiner Meinung nach eher weniger liegen.
    Immerhin verwenden die Intel und einige andere Prozessoren Little Endian und die restlichen heutzutage Big Endian. Die anderen Formen sind meines Wissens nirgends mehr zu finden.
    Und selbst bei Litte Endian müsste anstatt der "210007db" dann auch "db700021" rauskommen.

    Padding, so denke ich, kann man auch ausschließen, weil exakt alle 32 Bit des int-Wert (Alignment 4 Byte) verwendet werden und somit nichts aufgefüllt werden muss.

    Es dient eigentlich nur dem Verständnis, weil ich gern weiß wie die Dinge "unter der Haube" ausschauen, die ich nutze. Und ich dachte halt, dass die Speicherung von structs auch einem Standard folgen sollten (wie bei bei den Standardtypen eben auch).

    Bitte korrigiert mich, wenn ich falsch liege.



  • Auch die Standardtypen können durch Füllbytes ergänzt werden (Alignement).



  • Sorry. (Bin auf dem Sprung, nicht ganz gelesen) 🙄



  • C Beginner schrieb:

    Also an den Endians kann's meiner Meinung nach eher weniger liegen.
    Immerhin verwenden die Intel und einige andere Prozessoren Little Endian und die restlichen heutzutage Big Endian. Die anderen Formen sind meines Wissens nirgends mehr zu finden.
    Und selbst bei Litte Endian müsste anstatt der "210007db" dann auch "db700021" rauskommen.

    Padding, so denke ich, kann man auch ausschließen, weil exakt alle 32 Bit des int-Wert (Alignment 4 Byte) verwendet werden und somit nichts aufgefüllt werden muss.

    Es dient eigentlich nur dem Verständnis, weil ich gern weiß wie die Dinge "unter der Haube" ausschauen, die ich nutze. Und ich dachte halt, dass die Speicherung von structs auch einem Standard folgen sollten (wie bei bei den Standardtypen eben auch).

    Bitte korrigiert mich, wenn ich falsch liege.

    Mit der Endianes hat es nichts zu tun. kann es auch nicht, denn sonst würde sich das Programm unterschiedlich verhalten, jenach dem ob big- oder little endian vorliegt.

    Der Gedankenfehler, den Du gemacht hast, liegt darin, wie das Bitfeld aufgefüllt wird. Nicht vom höchstwertigen Bit wird aufgefüllt, sondern wie DirkB es schon gezeigt hat, vom niedrigsten Bit. Nur Dirks Schlußfolgerung mit der Endianess war falsch.

    Mach einfach mal folgenden Test:

    struct test
    	{
    		int hello:23;
    		int world:4;
    		int demo:5;
    	} variable;
    
    	variable.hello = 2011;
    	variable.world = 0;
    	variable.demo = 0;
    
    	printf( "%d\n", variable );
    

    Dabei muß immer 2011 herauskommen.

    mfg Martin


Anmelden zum Antworten