Struct Packing



  • Hallo,

    folgender Code:

    #include <cstddef> //offsetof
    
    #pragma pack(push, 8)
    
    struct Other
    {
    	int Offset0;
    	int Offset4;
    };
    
    struct Test
    {
    	float Offset0;
    	Other Offset8;
    };
    
    #pragma pack(pop)
    
    int main()
    {
    	auto s1 = sizeof(Other); //8
    	auto s2 = sizeof(Test);  //C
    
    	auto x1 = offsetof(Test, Offset0); //0
    	auto x2 = offsetof(Test, Offset8); //4
    
    	return 0;
    }
    

    Compiler ist VS2015 und erstellt wird ein x64 Projekt. (GCC zeigt das selbe Verhalten.)

    Das Problem ist, dass ich Test::Offset8 durch das 8 Byte Packing am Offset 8 erwarten würde und nicht an 4.
    Also so und mit einer Größe von 0xF von Test

    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
    | Offet0                        | Offset8                       |
    

    Das generierte Layout ist aber

    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
    | Offet0        | Offset8                       |
    

    Kann mir jemand erklären warum das so ist? Ich dachte das pack(8) sorgt dafür, dass nicht "passende" Member mit Padding aufgefüllt werden. Wenn Other 4 Byte groß wäre, würde die struct noch hinter das float passen und nicht gepaddet werden. Da Other aber mit 8 Byte größer als die Lücke ist, sollte Offset8 bei Offset 8 beginnen und nicht bei 4. 😕 😕



  • Ok, eventuell hab ichs raus.

    struct Test2
    {
    	float x;
    	double y;
    };
    

    Hier ist y wie erwartet bei 8. Sobald ich Other als

    struct alignas(8) Other
    {
    	int Offset0;
    	int Offset4;
    };
    

    anlege ist auch beim originalen Snippet das Offset richtig bei 8.

    Wird beim originalen Snippet nicht gepaddet, weil Other::Offset0 noch hinter den float passt? Ich hatte erwartet, dass die Other Struktur beim nächsten 8er Offset angelegt wird.