嵌套结构padding-C-64位-linux
我在C中有以下嵌套结构(64位) sizeof(Test)返回40个字节 我的问题是:嵌套结构padding-C-64位-linux,c,64-bit,nested,padding,structure,C,64 Bit,Nested,Padding,Structure,我在C中有以下嵌套结构(64位) sizeof(Test)返回40个字节 我的问题是: 填充1->为什么这是4个字节?这是因为内部结构本身应该对齐吗?。(另外,它是与8字节(长)还是16字节(内部大小)边界对齐?) padding2->这个4字节的填充是因为结构内部完成了最大对齐量(8) 谢谢 填充1->为什么这是4个字节?这是因为内部结构本身应该对齐吗?。(另外,它是与8字节(长)还是16字节(内部大小)边界对齐?) 这是因为内部的struct应该是8字节对齐的,因此long可以可靠地进行8字
struct
应该是8字节对齐的,因此long
可以可靠地进行8字节对齐
struct
的大小是8字节的倍数,因此内部struct
可以在8字节边界上适当对齐
在这种特殊情况下,如果匿名
struct
成员的处理方式与独立struct
成员的处理方式不同,则只需四个字节的填充就可以满足对齐要求,但是6.7.2.1
14结构或联合对象的每个非位字段成员以适合其类型的实现定义方式对齐
禁止这样做。因此,为了减小
struct
的大小,程序员需要重新排列它,将奇数个int
成员移过内部struct
(或者使int ab;
和长bc;
直接成员测试,而不经过匿名struct
).填充非常依赖于平台和编译器,即使您看到的行为非常常见
一般来说(这不是C标准所说的),编译器对齐结构的成员以减少内存访问的数量。对于64位x86,内存访问总是获取8个字节,与64位边界对齐。换句话说,如果访问地址0x1010AA45处的1个字节,CPU将实际从地址0x01010AA40处的(高速缓存)内存中提取8个字节
为了满足这样的规则,如果一个成员的长度为N字节,编译器通常将N四舍五入到2的下一次幂,并将该成员对齐到这样的大小,或者在64位平台上对齐8字节,无论哪个更小。不过,大多数编译器允许通过#pragma
或配置对此类规则进行调整
我相信您的编译器添加了Padding1,因为它有一个规则将所有结构与8字节边界对齐,无论它们有多大。或者,它也可以引入它,因为内部结构大于4字节,因此需要对齐到8字节
之所以引入Padding2,可能是因为您可以创建一个struct Test
数组。为了保证所有结构都正确地对齐到8字节边界,而不仅仅是数组中的第一项,定义了末尾的填充。“只有四个字节的填充可以满足对齐要求”——不,它们不能。任何包含bc
的结构都必须具有相同的对齐方式,因此内部结构和外部结构都必须是长对齐的,需要填充c
、ab
和d
。它是匿名结构,从不离开封闭结构。既然不能有任何独立的示例,为什么编译器不将它们视为用于布局目的的封闭结构的独立直接成员?字段不保证具有严格递增的地址吗?@AlanStokes是的,这是标准对布局做出的少数保证之一。可以移动d
成员的“人”是程序员,而不是编译器。@danielfisher,匿名或不匿名都不应该影响布局。不同编译单元之间的布局必须相同,即使字段的名称不同。代码不会编译。请只发布经过验证的真实编译代码,以生成声明的结果。鉴于实现在8字节边界上对齐长,所有填充都是C标准所要求的。。。a
和ab
都必须位于包含它们的结构的偏移量0处,强制在ab
之后和a
、b
或c
之后添加4个字节,并且在d
之前或之后必须有填充以进行数组元素对齐。
typedef struct {
int a;
int b;
int c;
struct {
int ab;
long bc;
}
int d;
} Test;
I see that,
a = 4 bytes
b = 4 bytes
c = 4 bytes
padding1 = 4 bytes
inner structure = 16 bytes ( 4 bytes for ab, 4 bytes padding, 8 bytes for bc)
d = 4 bytes
padding2 = 4 bytes