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
,而不是48
。 48
到底是从哪里来的?
如果这是一些奇怪的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 运算符返回不正确的大小? [复制]的主要内容,如果未能解决你的问题,请参考以下文章