Sizeof运算符返回不正确的大小?

时间:2011-12-01 20:08:44

标签: c struct x86-64 structure-packing

  

可能重复:
  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_t

出于某种原因,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,我如何确保结构的所有字段占用我想要它们占用的数量(我正在为这个结构投射一堆字节) )?

5 个答案:

答案 0 :(得分:3)

编译器可能会在struct的中间附加一些字节,以便对齐struct成员。结构的大小至少是其成员大小的总和,但不限于此。

答案 1 :(得分:3)

您还可以通过重新排序结构成员来摆脱填充。例如,如果你声明64位,然后是32位,然后是16位,然后是8位,那么它将自然对齐并且没有额外的填充字节。

答案 2 :(得分: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 :(得分:0)

对齐。某些数据类型在某些边界处对齐(读取:可被2整除的地址,例如16),这取决于体系结构,这会导致结构中的填充。

有一些编译器选项可以抑制此行为,and the gcc documentation tells you how to use the aligned attribute就可以了。

答案 4 :(得分:0)

这称为结构填充用于对齐

可能发生的是8位和16位值填充到32位,整个结构填充为机器字大小的倍数(8)。