为什么 x64 项目使用 16 的默认打包对齐?

lhu*_*ous 5 windows 64-bit visual-studio-2012

如果您在 VS2012 的 x64 项目中编译以下代码而没有任何 /Zp 标志:

#pragma pack(show)
Run Code Online (Sandbox Code Playgroud)

然后编译器会吐出:

value of pragma pack(show) == 16
Run Code Online (Sandbox Code Playgroud)

那么如果项目使用Win32的话,编译器会吐出:

value of pragma pack(show) == 8
Run Code Online (Sandbox Code Playgroud)

我不明白的是,Win64 中任何类型(即:long long 和指针)的最大自然对齐是 8。那么为什么不将 x64 的默认对齐设为 8?

与此有些相关,为什么有人会使用 /Zp16?

编辑:

这里有一个例子来说明我在说什么。即使对于 x64,指针具有 8 字节的自然对齐方式,Zp1 也可以强制它们达到 1 字节的边界。

struct A
{
    char a;
    char* b;
}

// Zp16
// Offset of a == 0
// Offset of b == 8

// Zp1
// Offset of a == 0
// Offset of b == 1
Run Code Online (Sandbox Code Playgroud)

现在,如果我们举一个使用 SSE 的例子:

struct A
{
    char a;
    char* b;
    __m128 c; // uses declspec(align(16)) in xmmintrinsic.h
}

// Zp16
// Offset of a == 0
// Offset of b == 8
// Offset of c == 16

// Zp1
// Offset of a == 0
// Offset of b == 1
// Offset of c == 16
Run Code Online (Sandbox Code Playgroud)

如果 __m128 确实是内置类型,那么我希望 Zp1 的偏移量为 9。但是由于它在 xmmintrinsic.h 中的定义中使用了 __declspec(align(16)),所以它胜过任何 Zp 设置。

所以这是我的问题,措辞有点不同:是否有一种类型为“c”,其自然对齐为 16B,但在前一个示例中的偏移量为 9?

Rog*_*and 4

此处的 MSDN 页面包含以下有关您的问题“为什么不为 x64 设置默认对齐方式 8?”的相关信息:

编写使用最新处理器指令的应用程序会带来一些新的限制和问题。特别是,许多新指令要求数据必须与 16 字节边界对齐。此外,通过将常用数据与特定处理器的缓存行大小对齐,可以提高缓存性能。例如,如果您定义一个大小小于 32 字节的结构体,您可能希望将其对齐到 32 字节,以确保有效地缓存该结构体类型的对象。