C中变量是如何在内存中分配的?

How variables are allocated in memory in C?

我正在看一本解释缓冲区溢出的书。我有一个基于 C 中缓冲区溢出输出的问题。 有两个字符数组(buffer_one[8]和buffer_two[8])和一个整数(值)。

x86_64 系统中,我按顺序声明变量。

    int value = 5; 
    char buffer_one[8], buffer_two[8];

然而,当我转储这三个变量的地址时,我按以下顺序收到它们(值在 d4,然后 buffer_one 在 d8,然后 buffer_two 在 e0)。

Buffer_one is at 0x7ffe7860b2d8 and contains one
Buffer_two is at 0x7ffe7860b2e0 and contains two
Value is at 0x7ffe7860b2d4 and contains 5

当我在 i686 系统中尝试时,我观察到不同的内存分配顺序(buffer_two 在 28,然后 buffer_one 在 30,然后值为 38)。

Buffer_one is at 0xbfef7330 and contains one
Buffer_two is at 0xbfef7328 and contains two
Value is at 0xbfef7338 and contains 5

我的问题:

  1. 为什么声明的内存分配顺序不同?
  2. 如果我在 int 之前声明两个 char 数组,为什么在 x86_64 系统中 int 变量总是分配在 buffer_two 之前?
  3. ARM架构中的顺序是什么?

编译器做它想做的事。或者编写编译器的开发人员喜欢做什么,取决于编译器是否有感知力。

这可能包括:

  • 编译器按照它读取定义的顺序分配内存。
  • 编译器保留一个只需要一个字节对齐的对象列表、一个需要两个字节对齐的对象列表、一个四字节对齐列表,等等。当它读取每个定义时,它会将那个对象放在适当的列表中。稍后,它首先为最严格的列表分配内存,从对齐的地址开始。然后它为下一个最严格的列表分配内存,依此类推。也许它会按照读取顺序处理每个列表中的项目。也许它以相反的顺序处理它们,只是因为列表是如何构造的。
  • 当编译器读取定义时,它会将标识符放入散列中 table,因为这是管理字符串的良好数据结构。稍后,当编译器分配内存时,它会按物理顺序处理散列 table。结果是对象排序混乱,用户看不到任何顺序。

C 标准没有指定任何有关不相关对象在内存中的顺序的信息。编译器做任何对他们的程序员有意义的事情。