众所周知,当我们声明局部变量时,它们会被存储到FILO中。但我被要求绘制一个图表来说明这些变量是如何被推入堆栈的?好吧,我对给出的示例代码感到困惑:
int giveMe_Red(int *xPos, int *yPos)
{
int count = 0;
int *nextpos, ifTreped;
int loc[8] = {0};
.
.
.
.
return count;
}
有没有人可以帮助我理解每个变量如何存储到内存中,比如数组,指针等等。比如说,在“0级”中“计数”,然后在堆栈的第1级或其他内容中使用“* nextpos”。如果有递归,那么它们是如何存储的?
答案 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
nextPos
ifTreped
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)仍然是标准参考。