6

我在 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)吗?

谢谢,

4

2 回答 2

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

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

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

它的存在使得整体的大小struct是八字节的倍数,因此内部struct可以在八字节边界上适当地对齐。

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

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

禁止这样做。因此,为了减小 的大小struct,程序员需要重新排列它,将奇数个int成员移动到内部struct(或不经过匿名的情况下创建int ab;long bc;直接成员)。Teststruct

于 2012-12-18T06:21:00.097 回答
0

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

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

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

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

可能会引入Padding2struct Test ,因为您可以创建一个. 为了保证所有结构都正确对齐到 8 字节边界 - 而不仅仅是数组中的第一项 - 定义了末尾的填充。

于 2012-12-18T06:48:43.103 回答