1

好的,我知道 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 .....你的评论对我帮助很大

4

5 回答 5

8

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

于 2012-07-16T22:15:51.590 回答
2

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

不幸的是,“堆栈”这个词是模棱两可的。

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

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

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

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

于 2012-07-16T23:17:25.953 回答
1

在许多(大多数)现代平台上,堆栈从内存中的较高地址增长到较低地址。IE。当您启动程序时,堆栈指针会立即放入内存中的某个地址,该地址由程序中的最大堆栈大小决定。一旦东西被压入堆栈,堆栈指针实际上会向下移动。

于 2012-07-16T23:33:47.677 回答
0

我可能是错的,但堆栈从较低的内存地址开始,然后被添加到。所以 var4 在上面是正确的。毕竟是栈!

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

于 2012-07-16T22:11:58.370 回答
0

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

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

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

于 2012-07-16T22:16:09.627 回答