我试图找出如何将地址分配给堆栈中的变量。我在下面运行了一个小程序:
int main()
{
long a;
int b;
int c;
printf("&a = %p\n", &a);
printf("&b = %p\n", &b);
printf("&c = %p\n", &c);
}
我预期的输出是(考虑到地址正在下降):
&a = 0x7fff6e1acb88
&b = 0x7fff6e1acb80
&c = 0x7fff6e1acb7c
但我得到了:
&a = 0x7fff6e1acb88
&b = 0x7fff6e1acb80
&c = 0x7fff6e1acb84
c
变量如何位于a
和b
变量之间?变量是否在声明时被放入堆栈?
我尝试将a
的类型从long
替换为int
,我得到了这个:
&a = 0x7fff48466a74
&b = 0x7fff48466a78
&c = 0x7fff48466a7c
在这里,我不明白为什么地址会上升,而它们之前会下降?
我使用gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-11precise2)
编译了程序,如果有任何帮助的话。
答案 0 :(得分:9)
变量是否在声明时没有放在堆栈上?
没有
为什么地址会上升,而之前它们会下降?
他们可能会上升,但他们不需要。
编译器可以自由地重置它认为合适的局部变量的顺序,或者它甚至可以删除或添加一些变量。
答案 1 :(得分:5)
变量不一定按照声明的顺序放在堆栈上。您无法预测堆栈上的 where - 它们可以按任何顺序排列。正如glglgl在评论中指出的那样,它们甚至不必存在于堆栈中,而只能存放在寄存器中。
答案 2 :(得分:5)
即使堆栈指针在给定CPU上向下计数,程序也将使用stack frames。如何在堆栈帧内分配某个参数是实现定义的。
另请注意,某些CPU具有向上计数堆栈指针。
另请注意,局部变量不一定在堆栈上分配。更常见的是,它们被分配在CPU寄存器中。但是当你获取变量的地址时,你会强迫编译器在堆栈上分配它,因为寄存器没有地址。
答案 3 :(得分:2)
堆栈增长的方向取决于架构。在x86
上,堆栈增长(从较高地址到较低地址)。如何将变量放在堆栈上还取决于OS的应用程序二进制接口(ABI)以及编译器如何遵循ABI约定。但是,编译器可能不一定遵循ABI约定。
答案 4 :(得分:1)
Agreeing with @Lundin您无法打印最有可能存在的寄存器地址。您可以做的最好的事情是转储目标代码并调查创建时发生的情况更多的局部变量然后是保存它们的寄存器数量。那时你会看到堆栈活动(在反汇编中)。
$ gcc -c main.c -o main.o
$ objdump -D main.o > main.dump
答案 5 :(得分:1)
这取决于编译器。 例如,我用“GNU GCC版本4.8.1”测试你的代码,编译器按顺序分配所有的语言环境变量:
&a = 0x7fffe265d118
&b = 0x7fffe265d114
&c = 0x7fffe265d110