Visual C++中的结构对齐

Dan*_*olf 6 c++ struct visual-c++

Visual C++提供编译器switch(/Zp)和packpragma来影响struct成员的aligment.但是,我似乎对它们如何运作有一些误解.

根据MSDN,对于给定的对齐值n,

成员的对齐将在边界上,该边界是n的倍数或成员大小的倍数,以较小者为准.

假设包的值为8个字节(这是默认值).在结构体中,我认为任何大小小于8字节的成员都将处于其自身大小的倍数的偏移量.大小为8字节或更大的任何成员将处于8字节的倍数的偏移量.

现在采取以下计划:

#include <tchar.h>

#pragma pack(8)

struct Foo {
    int i1;
    int i2;
    char c;
};

struct Bar {
    char c;
    Foo foo;
};

int _tmain(int argc, _TCHAR* argv[]) {
    int fooSize = sizeof(Foo); // yields 12
    Bar bar;
    int fooOffset = ((int) &bar.foo) - ((int) &bar); // yields 4

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Foo结构是在大小为12个字节.所以在内部Bar,我希望该Foo成员处于偏移8(8的倍数),而实际上它是偏移4.为什么呢?

而且,Foo实际上只有4 + 4 + 1 = 9字节的数据.编译器会在结尾处自动添加填充字节.但是,如果给定8字节的对齐值,它不应该填充到8的倍数而不是4吗?

任何澄清赞赏!

Dav*_*rtz 7

你的摘录解释了这一点,"以较小者为准".在32位平台上,a int是4个字节.4小于8.因此它具有4字节对齐.

packpragma导致事物被打包,而不是解压缩.除非有理由否则它不会填补.


Han*_*ant 6

首先请记住为什么对齐很重要。它的存在是为了让 cpu 能够快速读取内存,而无需复用字节。cpu 永远不会一口气读取一个结构体,它只访问它的成员。因此 Foo 结构体是 12 个字节这一事实并不重要。只有其成员的一致性才重要。鉴于没有 Foo 成员的对齐要求大于 4,Bar.foo 成员只需要对齐到 4。

Foo 是 12 个字节而不是 9 个字节也可以使用解释。编译器在末尾添加 3 个字节的填充,以便 Foo 数组的每个数组元素的成员仍然正确对齐。