堆栈是向上还是向下增长?堆栈

2023-09-07 02:48:02 作者:故里说长安

我在 c 中有这段代码:

I have this piece of code in c:

int q = 10;
int s = 5;
int a[3];

printf("Address of a: %d
",    (int)a);
printf("Address of a[1]: %d
", (int)&a[1]);
printf("Address of a[2]: %d
", (int)&a[2]);
printf("Address of q: %d
",    (int)&q);
printf("Address of s: %d
",    (int)&s);

输出是:

Address of a: 2293584
Address of a[1]: 2293588
Address of a[2]: 2293592
Address of q: 2293612
Address of s: 2293608

所以,我看到从 aa[2],内存地址每个增加 4 个字节.但是从qs,内存地址减少了4个字节.

So, I see that from a to a[2], memory addresses increases by 4 bytes each. But from q to s, memory addresses decrease by 4 byte.

我想知道两件事:

堆栈是向上还是向下?(在这种情况下,我觉得两者都是)a[2]q 内存地址之间发生了什么?为什么那里有很大的内存差异?(20 字节). Does stack grow up or down? (It looks like both to me in this case) What happen between a[2] and q memory addresses? Why there are a big memory difference there? (20 bytes).

注意:这不是家庭作业问题.我很好奇堆栈是如何工作的.感谢您的帮助.

Note: This is not homework question. I am curious on how stack works. Thanks for any help.

推荐答案

堆栈的行为(向上或向下)取决于应用程序二进制接口 (ABI) 以及调用堆栈(也称为激活记录)的组织方式.

The behavior of stack (growing up or growing down) depends on the application binary interface (ABI) and how the call stack (aka activation record) is organized.

程序在其整个生命周期中都必须与其他程序(如操作系统)进行通信.ABI 确定一个程序如何与另一个程序通信.

Throughout its lifetime a program is bound to communicate with other programs like OS. ABI determines how a program can communicate with another program.

不同架构的堆栈可以以任何一种方式增长,但对于一个架构,它将是一致的.请查看 此 wiki 链接.但是,堆栈的增长是由该架构的 ABI 决定的.

The stack for different architectures can grow the either way, but for an architecture it will be consistent. Please check this wiki link. But, the stack's growth is decided by the ABI of that architecture.

例如,如果你使用 MIPS ABI,调用堆栈定义如下.

For example, if you take the MIPS ABI, the call stack is defined as below.

让我们考虑函数fn1"调用fn2".现在'fn2'看到的堆栈帧如下:

Let us consider that function 'fn1' calls 'fn2'. Now the stack frame as seen by 'fn2' is as follows:

direction of     |                                 |
  growth of      +---------------------------------+ 
   stack         | Parameters passed by fn1(caller)|
from higher addr.|                                 |
to lower addr.   | Direction of growth is opposite |
      |          |   to direction of stack growth  |
      |          +---------------------------------+ <-- SP on entry to fn2
      |          | Return address from fn2(callee) | 
      V          +---------------------------------+ 
                 | Callee saved registers being    | 
                 |   used in the callee function   | 
                 +---------------------------------+
                 | Local variables of fn2          |
                 |(Direction of growth of frame is |
                 | same as direction of growth of  |
                 |            stack)               |
                 +---------------------------------+ 
                 | Arguments to functions called   |
                 | by fn2                          |
                 +---------------------------------+ <- Current SP after stack 
                                                        frame is allocated

现在您可以看到堆栈向下增长.因此,如果将变量分配到函数的局部帧,则变量的地址实际上是向下增长的.编译器可以决定内存分配的变量顺序.(在您的情况下,首先分配的堆栈内存可以是q"或s".但是,通常编译器会按照变量声明的顺序进行堆栈内存分配).

Now you can see the stack grows downward. So, if the variables are allocated to the local frame of the function, the variable's addresses actually grows downward. The compiler can decide on the order of variables for memory allocation. (In your case it can be either 'q' or 's' that is first allocated stack memory. But, generally the compiler does stack memory allocation as per the order of the declaration of the variables).

但是在数组的情况下,分配只有一个指针,需要分配的内存实际上是由一个指针指向的.对于数组,内存需要是连续的.因此,虽然堆栈向下增长,但对于数组,堆栈却向上增长.

But in case of the arrays, the allocation has only single pointer and the memory needs to be allocated will be actually pointed by a single pointer. The memory needs to be contiguous for an array. So, though stack grows downward, for arrays the stack grows up.