Sizeof 运算符返回不正确的大小? [复制]

Posted

技术标签:

【中文标题】Sizeof 运算符返回不正确的大小? [复制]【英文标题】:Sizeof operator returns incorrect size? [duplicate] 【发布时间】:2011-12-01 20:08:43 【问题描述】:

可能重复: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,我如何确保结构的所有字段占据我希望它们占据的数量(我正在向这个结构投射一堆字节)?

【问题讨论】:

【参考方案1】:

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

【讨论】:

哦,所以我需要volatile struct 您需要添加__attribute__((packed)) @Nick 请注意,使用packed 可能会影响程序的性能。未对齐的内存访问可能比对齐的访问更昂贵,并且可以在循环中产生可衡量的差异。【参考方案2】:

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

【讨论】:

【参考方案3】:

由于结构填充(不确定这里的术语是什么)。最大的字段是 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

【讨论】:

【参考方案4】:

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

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

【讨论】:

【参考方案5】:

这称为对齐结构填充

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

【讨论】:

以上是关于Sizeof 运算符返回不正确的大小? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

sizeof和strlen的区别

当 sizeof 的大小与实际对象大小不匹配时,一切如何工作(包括运算符'->')?

strlen与sizeof

sizeof和strlen

sizeof和strlen

strlen()函数和sizeof算符