自动局部变量是否存储在C中的堆栈中?

时间:2012-07-16 22:09:15

标签: c memory gcc local-variables

好吧我知道main()自动局部变量存储在堆栈中,也是任何函数自动局部变量,但是当我在gcc版本4.6.3上尝试了以下代码时:

#include <stdio.h>

    int main(int argc, char *argv[]) {

        int var1;
        int var2;
        int var3;
        int var4;
        printf("%p\n%p\n%p\n%p\n",&var1,&var2,&var3,&var4);
        }

结果是:

0xbfca41e0
0xbfca41e4
0xbfca41e8
0xbfca41ec

根据堆栈顶部的var4和堆栈底部的var1以及堆栈指针现在指向var1地址下面的地址....但是为什么var4上的 堆栈的顶部和底部的var1 ...它在var1之后声明,所以我认为逻辑上var1应该在堆栈的顶部,var1之后声明的任何变量应该在 它在记忆中...所以在我的例子中这样:

>>var1  at 0xbfca41ec
>>var2  at 0xbfca41e8
>>var3  at 0xbfca41e4
>>var4  at 0xbfca41e0
>>and stack pointer pointing here  
..

..

编辑1:

在阅读@AusCBloke的评论后,我尝试了以下代码:

#include <stdio.h>


 void fun(){
 int var1;
 int var2;
 printf("inside the function\n");
 printf("%p\n%p\n",&var1,&var2);

 }


 int main(int argc, char *argv[]) {


int var1;
int var2;
int var3;
int var4;



printf("inside the main\n");
printf("%p\n%p\n%p\n%p\n",&var1,&var2,&var3,&var4);
fun();
return 0;
}

和结果:

inside the main
0xbfe82d60
0xbfe82d64
0xbfe82d68
0xbfe82d6c
inside the function
0xbfe82d28
0xbfe82d2c

所以fun()堆栈框架内的变量位于main()堆栈框架内的变量之下,根据堆栈的性质,这是真的,但是在同一堆栈框架内,不需要从顶部到底部。

感谢@AusCBloke .....你的评论给了我很多帮助

5 个答案:

答案 0 :(得分:8)

不要求按照声明的顺序分配这些变量。它们可以被编译器移动,甚至完全优化。如果您需要相对地址保持不变,请使用struct

答案 1 :(得分:2)

具有自动存储持续时间的对象通常存储在堆栈中,但语言标准不需要它。事实上,the standard(链接是最新的预发布C11草案) 甚至没有提到“堆叠”这个词。

遗憾的是,“堆叠”一词含糊不清。

从最抽象的意义上说,堆栈是一种数据结构,其中最先添加的项目首先被删除(后进先出,或LIFO)。关于具有自动存储持续时间的对象的生命周期的要求(即,在没有static关键字的函数中定义的对象)暗示一些类型的堆栈分配。

单词“stack”也常用于表示连续的内存区域,通常由指向最顶层元素的“堆栈指针”控制。通过将堆栈指针移离基座来增加堆栈,并通过将堆栈指针移向基座来收缩。 (它可以朝任何方向增长,朝向更高或更低的内存地址。)大多数C编译器使用这种连续堆栈来实现自动对象 - 但并非所有人都这样做。 IBM主机系统有C编译器,它们从类似堆的结构中为函数调用分配存储空间,而嵌套调用的地址不需要按递增或递减顺序统一。

这是一种不寻常的实现,并且有很好的理由不常用这种方法(连续堆栈更简单,更高效,并且通常由CPU支持)。但是C标准是经过精心编写的,以避免需要特定的方案,并且无论编译器选择哪种方法,精心编写为可移植的C代码都能正常工作。 您不需要知道。您真正需要了解的var1地址就是它&var1。如果你写if (&var1 < &var2) { ... },那么你可能做错了(表达式的行为未定义,BTW)。

这是标准的C答案。我看到您的问题被标记为。据我所知,所有版本的gcc都使用连续的堆栈。但即便如此,利用这一点也很少有任何好处。

答案 2 :(得分:1)

许多(大多数)现代平台堆栈从内存中的较高地址增长到较低地址。 I..e。当您启动程序时,堆栈指针会立即放入内存中的某个地址,这取决于程序中的最大堆栈大小。一旦事物被推入堆栈,堆栈指针实际上是向下移动

答案 3 :(得分:0)

我可能错了,但堆栈从较低的内存地址开始,然后添加到。因此,将var4放在首位是正确的。毕竟这是一堆!

编辑:它后面的汇编代码在堆栈指针位于内存堆栈的底部,每当添加数据时,堆栈指针都会递增,以便下一个变量落在ontop上。

答案 4 :(得分:0)

我99.9999%肯定答案是是。此外,堆栈在英特尔架构机器上向下增长,而不是向上。较低的区域成为堆栈的虚拟“顶部”(可以说是倒置的)。

从技术上讲,变量在堆栈内存中的顺序是

编辑:但这可能仍然是特定于编译器的。