2011-12-01 49 views
0

可能重複:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
Extra bytes when declaring a member of a struct as uint32_tSizeof運算符返回不正確的大小?

出於某種原因,該sizeof操作者返回一個假的尺寸爲這樣的結構(的48代替40):

typedef struct mbdb_file_info { 
    uint16_t mode; 

    uint32_t unk0; 
    uint32_t unk1; 
    uint32_t user_id; 
    uint32_t group_id; 

    uint32_t time0; 
    uint32_t time1; 
    uint32_t time2; 

    uint64_t length; 
    uint8_t flag; 
    uint8_t property_count; 
} mbdb_file_info; 

因此,這裏是一個簡單的測試:

printf("%ld %ld %ld %ld: %ld", sizeof(uint8_t), 
           sizeof(uint16_t), 
           sizeof(uint32_t), 
           sizeof(uint64_t), 
           sizeof(mbdb_file_info)); 

它打印:

1 2 4 8:48

這是如何發生的呢?如果您將所有尺寸一起添加,您可以獲得40,而不是4848從哪裏來?

如果有些奇怪的x86-64 perk,我該如何確保結構的所有字段佔用我希望它們佔據的數量(我正在爲此結構投擲一堆字節)?

回答

3

編譯器可能會在結構的中間追加一些字節以對齊結構成員。結構的大小至少是其成員大小的總和,但不限於此。

+0

哦,所以我需要'volatile struct'? –

+0

您需要添加'__attribute __((packed))'。 –

+4

@Nick請注意,使用'packed' *可能會影響程序的性能。未對齊的內存訪問可能比對齊的訪問更昂貴,並且可能會在循環中產生可衡量的差異。 –

0

這叫做結構填充用於比對

可能發生的情況是,8位和16位值被填充到32位,並且整個結構被填充爲機器字大小(8)的倍數。

1

由於結構填充(不確定這是哪裏的術語)。最大的領域是64位,所以一切都按照它排列。所以,我們有:

typedef struct mbdb_file_info { 
    uint16_t mode; // 16 + 

    uint32_t unk0; // 32 = 48, so add 16 more to align to 64bit; 
    uint32_t unk1; // this 
    uint32_t user_id; // and this give 64bits ; 
    uint32_t group_id; // again this 

    uint32_t time0; // plus this - 64bits; 
    uint32_t time1; // this 
    uint32_t time2; // and this = 64bit ; 

    uint64_t length; // this is 64 by itself 
    uint8_t flag; // this 
    uint8_t property_count; // +this is 16, add 48 for the alignment 
} mbdb_file_info; // when you sum all bits (+ the additional for padding) 
         // you have exactly 48B 
3

你也可以通過重新排序你的結構成員來擺脫填充。例如,如果聲明64位,32位,16位和8位,它將自然對齊,並且不會有額外的填充字節。