需要解释内存地址如何在这个C程序中工作

时间:2012-08-06 05:24:44

标签: c memory

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

答案 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无关。 基本上是编译器发现当时空的连续空间(或内存块)是空的,因此它将它分配给你的程序。