堆栈变量如何在64/32位机器上对齐?

时间:2017-05-11 22:31:38

标签: c visual-studio-2010 stack

我一直试图了解编译器如何在64 / 32bit机器上对齐堆栈变量。

看看下面的代码:

void Test()
{
    int x = 1;
    int y = 2;
    int z = 3;
}

我发现:

  • &x > &y > &z是真的。
  • &x - &y&y - &z对他们两个都是3。

这意味着每个变量被8个额外字节填充。对于64位机器上的32位应用程序,我期望变量不需要任何对齐,即差异应该是1而不是3。

有人可以解释一下吗? 谢谢!

环境详情:

64位Windows 7,Visual Studio 2010,应用程序配置:x86

1 个答案:

答案 0 :(得分:2)

正如@HansPassant和其他人所指出的,堆栈上的变量对齐是一个实现细节。一旦启用了优化,你甚至不能确定它们中的任何一个在堆栈中(除非你获取它的地址) - 每个都可以优化到寄存器。

只是为了说明:测试程序

#include <stdio.h>
#include <windows.h>

int main() {
    int x = 1, y = 2, z = 3;
    printf("%d,%d,%d,%d\n",&y-&x,&z-&y,(BYTE*)&y-(BYTE*)&x,(BYTE*)&z-(BYTE*)&y);
}

在这里打印(win7 x64,vs2012 x86编译器):

>cl /nologo t.c >nul && t.exe
2,-1,8,-4

>cl /Ox /nologo t.c >nul && t.exe
-2,1,-8,4

>cl /RTC1 /Ox /nologo t.c >nul && t.exe
-3,-3,-12,-12

在最后一种情况下,/ RTC在变量to detect out-of-bounds access之间插入间隙。

关于默认路由,编译器遵守英特尔的建议,因为x86在访问未对齐数据时会受到惩罚。这里,具体来说,它是 Intel® 64 and IA-32 Architectures Optimization Reference Manual,第3.6.7节“堆栈对齐”

  

当a时,会发生对堆栈的未对齐访问的性能损失   内存引用拆分缓存行。这意味着八分之一   空间连续的未对齐四字访问总是受到惩罚,   类似地,对于4个连续的非对齐双四字中的一个   访问等。

     

任何时候对齐堆栈都可能是有益的   超出系统默认堆栈对齐的数据对象。   例如,在32 / 64bit Linux和64bit Windows上,默认堆栈   对齐是16个字节,而32位Windows是4个字节。

     

汇编/编译器编码规则55.(H影响,M概括性) 确保   堆栈以最大的多字节粒度数据类型对齐   边界匹配寄存器宽度。

对于较长的类型(浮点),even higher alignments are recommended for the same purpose