0

我有一个非常简单的 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

我的问题是:为什么地址似乎越来越小?这有什么逻辑吗?谢谢你。

4

4 回答 4

1

允许编译器对您的自动变量执行任何操作。在这种情况下,它看起来就像是将它们连续放在堆栈上。在当今使用的最流行的系统上,堆栈向下增长。

于 2012-08-06T05:27:16.790 回答
1

大多数编译器在一个步骤中为局部变量分配堆栈内存,在函数的一开始。内存被分配为单个连续块。在这些情况下,编译器显然可以自由地为该块内的局部变量使用任何内存布局。如果可以将它们放在那里,以便地址按声明顺序增加。或减少。或者随机排列。这是一个实现细节。它背后没有太多逻辑。

在您的情况下,编译器很可能试图“假装”数组的内存是按顺序和独立地在堆栈中分配的(即使情况并非如此)。如果在您的平台堆栈上向下增长(就像在许多平台上一样),那么预计稍后声明的对象将具有较小的地址。

但同样,函数不会单独分配本地对象。最重要的是,该语言不保证本地对象地址之间的任何关系。因此,没有真正的理由更喜欢一种订购方式而不是另一种订购方式。

于 2012-08-06T05:36:58.977 回答
1

C 程序的输出依赖于平台和编译器。不可能只有一个完美的答案,因为地址安排因以下因素而异:系统是小端还是大端。您正在编译什么样的操作系统。您正在为哪种内存架构进行编译。您使用的是哪种编译器(编译器也可能有错误)无论您是在 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 源代码打印的地址表明堆栈正在向下增长。

于 2012-08-06T06:24:39.540 回答
0

基本上编译器有责任为所有变量分配内存。数组在堆栈上获取地址。但这与您获得的o / p无关。基本上事情是编译器当时发现连续空间(或内存块)是空的,因此它将它分配给您的程序。

于 2012-08-06T07:21:23.150 回答