局部变量如何存储在堆栈中?

时间:2013-09-30 06:23:27

标签: c

众所周知,当我们声明局部变量时,它们会被存储到FILO中。但我被要求绘制一个图表来说明这些变量是如何被推入堆栈的?好吧,我对给出的示例代码感到困惑:

int giveMe_Red(int *xPos, int *yPos)
{
   int count = 0;
   int *nextpos, ifTreped;
   int loc[8] = {0};
   .
   .
   .
   .
   return count;
}

有没有人可以帮助我理解每个变量如何存储到内存中,比如数组,指针等等。比如说,在“0级”中“计数”,然后在堆栈的第1级或其他内容中使用“* nextpos”。如果有递归,那么它们是如何存储的?

2 个答案:

答案 0 :(得分:3)

细节取决于处理器,但是例如在x86中,所有变量的堆栈空间通过单个减法一次分配给esp。 标准序言是

push ebp                ; Save old base pointer
mov  ebp, esp           ; Mark current base pointer
sub  esp, stack_space   ; Allocate stack space
结语是

mov esp, ebp            ; Free stack space
pop ebp                 ; Reload old base pointer
ret                     ; Return to caller

在你的情况下,所需的空间(假设是32位,那些都是当地人)将是

  • count
  • 的4个字节
  • 4 for nextPos
  • 4 for ifTreped
  • {li> 4 * 8表示loc数组

总共44个字节(保存ebp所需空间为+4)。

sub esp, 44之后,会有代码将loc的所有元素归零。

修改

用gcc检查后,似乎分配的空间是48字节(不是44),不确定原因,但可能是堆栈对齐原因。

答案 1 :(得分:0)

乔纳森的回答是正确的,但没有回答你的问题。因此,让我们采取最简单的情况,假设没有优化,所有参数都在堆栈上传递,32位整数,32位地址,堆栈向下增长,调用者清理。 在调用giveme_red之前,SP指向某处。为了能够从调用返回,您需要堆栈上的返回地址,即四个字节。两个int参数也在堆栈上,每个4个字节,因此SP现在比原来的减少了12个字节。一旦调用了giveme_red,就需要更多的空间:4个字节用于计数,4个字节用于int指针,4个用于“iftreped”,最后8个用于int数组。 为了能够实现递归(giveme_red直接或通过另一个函数间接调用自身),giveme_red将需要设置一个新的堆栈帧来调用自身。重复与上述相同的顺序。通常还有一个技巧,因为您需要能够访问本地变量,并且通常会保存和恢复另一个名为BP的寄存器(在堆栈上)。如果你想了解更多Aho,Sethi,Ullman,Lam:Compilers(The Dragon Book)仍然是标准参考。