根据维基:
the caller pushes the return address onto the stack, and the called subroutine, when it finishes, pops the return address off the call stack and transfers control to that address.
图片来自维基:
这个我不是很明白。 假设我有一个 C 程序如下:
#include <stdio.h>
int foo(int x)
{
return x+1;
}
void spam()
{
int a = 1; //local variable
int b = foo(a); //subroutine called
int c = b; //local variable
}
int main()
{
spam();
return 0;
}
而且我认为调用堆栈应该是如下图所示:
<None> means none local variables or params
_| parameters for foo() <int x> |_
top | local of spam() <int c> |
^ | return address of foo() |<---foo() called, when finishes, return here?
| | local of spam() <int b> |
bot | local of spam() <int a> |
_| parameters for spam() <None> |_
| locals of main() <None> |
| return address of spam() |<---spam() called, when finishes, return here?
| parameters for main() <None> |
问题:
根据引用维基的话,
the called subroutine, when it finishes, pops the return address off the call stack and transfers control to that address.
1.我画的对吗?
2.如果是正确的,那么当foo()结束时,它会
pop the return address off the call stack and transfer control to that address
,但是它如何弹出返回地址呢? 因为当 foo 完成时,当前堆栈指针指向垃圾邮件的本地, 对吧?
更新:
如果 main() 看起来像这样会怎样:
int main()
{
spam();
foo();
}
那么调用栈应该是什么样的呢?
最佳答案
您的绘图不正确。函数的局部堆栈变量都在任何返回地址之下。否则,正如您所观察到的,当您调用函数时,局部变量会丢失。
应该是这样的:
| parameters for foo() <int x> |
| return address of foo() |
| local of spam() <int c> |
| local of spam() <int b> |
| local of spam() <int a> |
| parameters for spam() <None> |
| return address of spam() |
| locals of main() <None> |
| parameters for main() <None> |
我认为混淆是因为您认为变量声明被视为语句并按顺序执行。事实上,编译器通常会分析一个函数来决定所有局部变量需要多少堆栈空间。然后它发出代码来相应地调整堆栈指针,并在函数入口处进行调整。然后,对其他函数的任何调用都可以压入堆栈,而不会干扰此函数的堆栈框架。
关于对函数调用栈的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7493785/