2

可能重复:
为什么结构的 sizeof 不等于每个成员的 sizeof 之和?
将结构的成员声明为 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,不是48。到底是48从哪里来的?

如果这是一些奇怪的x86-64特权,我如何确保结构的所有字段占据我希望它们占据的数量(我正在向这个结构投射一堆字节)?

4

5 回答 5

5

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

于 2011-12-01T20:10:25.317 回答
3

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

于 2011-12-01T20:16:32.920 回答
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
于 2011-12-01T20:15:37.523 回答
0

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

有一些编译器选项可以抑制这种行为,gcc 文档告诉你如何使用它的aligned属性

于 2011-12-01T20:10:45.903 回答
0

这称为对齐的结构填充

可能发生的情况是 8 位和 16 位值被填充到 32 位,并且整个结构被填充为机器字长 (8) 的倍数。

于 2011-12-01T20:11:25.613 回答