这个问题是关于c和c++中对于参数,变量在内存中地址分配的问题。对于以下代码
int main (int argc, char *argv[]) { int a; int b; a = 1; b = 2; return 0; }
我的理解是,main函数是通过初始函数调用,main函数实际和其他函数一样。
在初始函数调用main函数后,会先将返回地址压入堆栈,接着将参数压入堆栈。面对函数中定义的局部变量,将会按照定义顺序分配堆栈内存空间。而堆栈是从高地址向低地址生长的,所以我认为&a > &b。
然而,在gdb调试过程中,我发现&b > &a。请问我的理解在哪里错了?
局部变量的空间不是一个一个压入栈中的,而是一次性分配好的,所以理解为变量依次入栈是错误的。C语言也没有规定局部变量在内存中的位置,只是常常实现为先定义的变量在高地址、后定义的变量在低地址。不过局部变量在栈上的位置没有绝对的关系,甚至不一定会出现在栈上。比如你的代码做这样的调整,改成下面这样:
这个时候你会发现a变量确实分配在高地址,而b变量分配在低地址。如果你把你的程序加上-O2参数优化一下,那么a和b这两个变量因为没有被真正的使用,而被编译器优化掉,你直接p &a会得不到任何的值。
“栈”这个数据结构本身并没有规定其生长的方向,具体实现中向高地址或者低地址生长都无妨。但是对于操作系统而言,栈的生长方向一般是取决于处理器对PUSH/POP操作的实现。对于x86来说,PUSH以后SP/ESP的值是减小,因此它是向低地址生长的,样例代码:
而声明一个变量,无非是告诉编译器,在栈上给它准备一块空间。因此你所提及的情况,实际上与栈无直接关系:a先声明的话,就一定会先在栈上为它分配空间吗?举个最简单的栗子,如果a根本没被用到,编译器完全可以不为它分配空间。所以这个最终还是取决于编译器的实现。
补充一段WIKI吧:
系统分配的内存区叫“栈区”,手动分配的内存空间叫“堆区”。
在“栈区”地址扩展方向是从高地址向低地址,“堆区”相反。
lz 你帖下编译命令?