嵌套结构填充 - C - 64位 - linux

时间:2012-12-18 06:18:16

标签: c 64-bit nested padding structure

我在C中有以下嵌套结构(64位)

    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

sizeof(Test)返回40个字节。

我的问题:

  1. padding1 - >为什么这4个字节?这是因为内部结构本身应该对齐吗? (另外,它是与8字节(长)还是16字节(内部大小)边界对齐。?)

  2. padding2 - >这是4字节填充,因为在结构内部完成了最大的对齐(这是8)??

  3. 谢谢,

2 个答案:

答案 0 :(得分:4)

  
      
  1. padding1 - >为什么这4个字节?这是因为内部结构本身应该对齐吗? (另外,它是与8字节(长)还是16字节(内部大小)边界对齐。?)
  2.   

这是因为内部struct应该是8字节对齐的,因此long可以可靠地进行8字节对齐。

  
      
  1. padding2 - >这是4字节填充,因为在结构内部完成了最大的对齐(这是8)??
  2.   

这是因为整个struct的大小是八个字节的倍数,因此内部struct可以在八字节边界上适当地对齐。

在这种特殊情况下,如果匿名struct成员可以与独立struct处理不同,但只有四个字节的填充,则可以满足对齐要求,但是6.7.2.1

  

14结构或联合对象的每个非位字段成员都以适合其类型的实现定义方式对齐。

禁止这样做。因此,为了减小struct的大小,程序员需要重新排列它,将奇数个int成员移过内部struct(或使int ab;和{{ 1}} long bc;的直接成员,无需通过匿名Test)。

答案 1 :(得分:0)

Padding非常依赖于平台和编译器,即使您看到的行为非常常见。

通常(这不是C标准所说的),编译器会对齐结构的成员,以减少内存访问次数。对于64位x86,内存访问总是获取8个字节,与64位边界对齐。换句话说,如果在地址 0x1010AA45 访问1个字节,CPU将实际从地址 0x01010AA40 的(缓存)内存中取出8个字节。

为了满足这样的规则,如果一个成员是N字节长,编译器通常将N舍入到下一个2的幂,并将该成员与64位平台上的大小或8字节对齐,无论小什么。大多数编译器允许通过#pragma或配置来调整此规则。

我相信你的编译器会添加 Padding1 ,因为它有一个规则可以将所有结构与8字节边界对齐,无论它们有多大。或者,它也可以引入它,因为内部结构大于4个字节,因此需要对齐到8个字节。

可能会引入

Padding2 ,因为您可以创建struct Test数组。为了保证所有结构都正确对齐到8字节边界 - 而不仅仅是数组中的第一项 - 定义了最后的填充。