5

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

#pragma pack(show)

然后编译器会吐出:

value of pragma pack(show) == 16

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

value of pragma pack(show) == 8

我不明白的是,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

现在,如果我们举一个使用 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

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

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

4

2 回答 2

4

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

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

于 2013-04-15T14:44:32.867 回答
1

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

在 x64 上,浮点在 SSE 单元中执行。你说最大的类型有对齐 8。但这是不正确的。某些 SSE 内在类型,例如__m128,具有 16 位对齐。

于 2013-04-15T20:30:57.297 回答