我有一个非常简单的C程序,我(出于我自己的好奇心)调查哪些内存地址用于分配局部变量。我的节目是:
#include <stdio.h>
int main()
{
char buffer_1[8], buffer_2[8], buffer_3[8];
printf("address of buffer_1 %p\n", buffer_1);
printf("address of buffer_2 %p\n", buffer_2);
printf("address of buffer_3 %p\n", buffer_3);
return 0;
}
输出如下:
address of buffer_1 0x7fff5fbfec30
address of buffer_2 0x7fff5fbfec20
address of buffer_3 0x7fff5fbfec10
我的问题是:为什么地址似乎越来越小?这有什么逻辑吗?谢谢。
答案 0 :(得分:1)
允许编译器对自动变量执行任何操作。在这种情况下,它看起来就像是将它们连续放在堆栈上。在当今使用最流行的系统中,堆栈会向下扩展。
答案 1 :(得分:1)
大多数编译器在函数的最开始一步为本地变量分配堆栈内存。存储器被分配为单个连续块。在这种情况下,编译器显然可以自由地使用该块内局部变量的任何内存布局。如果可以将它们放在那里,以便地址按声明的顺序增加。或减少。或随机排列。这是一个实现细节。而且背后没有太多的逻辑。
很有可能在你的情况下,编译器试图“假装”数组的内存顺序和独立地分配在堆栈中(即使不是这种情况)。如果您的平台堆栈向下增长(就像在许多平台上一样),那么预期稍后声明的对象将具有较小的地址。
但同样,函数不会单独分配本地对象。最重要的是,语言不保证本地对象地址之间的任何关系。所以,没有理由偏好一个订购而不是另一个。
答案 2 :(得分:1)
C程序的输出取决于平台,取决于编译器。 不能只有一个完美的答案,因为地址安排因以下因素而异: 系统是小还是大端。 你正在编译什么样的操作系统。 您正在编译什么样的内存架构。 你正在使用什么样的编译器(编译器也可能有bug) 无论您使用的是64位还是32位平台。 还有更多。
但最重要的是,处理器架构的类型。 :)
以下是每个处理器的堆栈增长策略列表:
x86,PDP11 Downwards
System z In a linked list fashion, downwards, mostly.
ARM Select-able and can grow in either up or downward.
Mostek6502 Downwards (but only 256 bytes).
SPARC In a circular fashion with a sliding window, a limited depth stack.
RCA1802A Subject to SCRT(Standard Call and Return Technique) implementation.
但是,通常,编译时编译器应将这些地址映射到生成的二进制文件中。然后在运行时,二进制文件可能占用(或可能假装占用)一组顺序的存储器地址。在你的情况下,你的C源打印的地址显示堆栈正在向下增长。
答案 3 :(得分:0)
编译器基本上有责任为所有变量分配内存。 数组在堆栈上获取地址。但它与你得到的o / p无关。 基本上是编译器发现当时空的连续空间(或内存块)是空的,因此它将它分配给你的程序。