gcc如何将局部变量推送到堆栈?

时间:2014-11-19 19:22:05

标签: variables gcc stack allocation

void
f
    ()
{
    int a[1];
    int b;
    int c;
    int d[1];
}

我发现这些局部变量(例如)不会按顺序推送到堆栈。 b和c按其声明的顺序推送,但是,a和d组合在一起。因此,编译器以不同于任何其他内置类型或对象的方式分配数组。

这是C / C ++要求还是gcc实施细节?

2 个答案:

答案 0 :(得分:3)

C标准没有说明分配局部变量的顺序。它甚至不使用“堆栈”这个词。它只要求局部变量的生命周期从进入最近的封闭块开始(基本上当执行到达{时)并从该块退出时结束(到达{{1每个对象都有一个唯一的地址。它确实承认两个不相关的变量可能碰巧在内存中相邻(由于涉及指针算术的模糊技术原因),但没有说明何时会发生这种情况。

分配变量的顺序完全取决于编译器的奇思妙想,您不应编写依赖于任何特定顺序的代码。编译器可能按照它们声明的顺序排列局部变量,或按名称按字母顺序排列,或者如果碰巧导致代码更快,它可能会将一些变量组合在一起。

如果需要按特定顺序分配变量,可以将它们包装在数组或结构中。

(如果你要查看生成的机器代码,你很可能会发现变量没有被“逐个推入堆栈”。相反,编译器可能会生成一条指令来调整堆栈指针由一定数量的字节组成,有效地分配一块内存来保存 all 函数或块的局部变量。访问给定变量的代码将在堆栈帧中使用它的偏移量。 )

由于你的函数没有对其局部变量做任何事情,编译器可能根本不会为它们分配空间,特别是如果你使用}或类似的东西请求优化。

答案 1 :(得分:2)

编译器可以根据需要对局部变量进行排序。它甚至可以选择根本不分配它们(例如,如果它们没有被使用,或者通过传播/ ciscizing /保持寄存器/等来优化)或者为多个具有不相交的现场的本地分配相同的堆栈位置的范围内。

没有通用的实现细节来概述特定编译器如何执行它,因为它可能随时更改。

通常情况下,编译器会尝试将类似大小的变量(和/或路线)组合在一起,以通过“间隙”最大限度地减少浪费的空间,但还有很多其他因素。

结构和数组的要求略有不同,但我认为这超出了这个问题的范围。