编译器如何知道函数调用后控件应返回的位置?

时间:2013-03-07 14:56:37

标签: c++

考虑以下功能:

int main()
{
    //statement(s);
    func1();
    //statement(s);
}

void func1()
{
    //statement(s);
    func2();
    //statement(s);
}

void func2()
{
    //statement(s);
}

func2执行了所有操作后,编译器如何知道返回的位置?我知道控件转移到函数func1(确切地说是哪个语句),但 编译器知道它?什么告诉编译器返回哪里?

4 个答案:

答案 0 :(得分:15)

这通常使用call stack

来实现
  • 当控件转移到一个函数时,返回的地址被压入堆栈。
  • 当函数完成时,地址从堆栈中弹出并用于将控制权转移回被调用者。

详细信息通常由编译代码的硬件体系结构强制执行。

答案 1 :(得分:3)

实际上,编译器没有运行代码,但是机器运行,并且当它调用新函数时,它存储 next 指令的地址,该指令在当前函数之后执行在堆栈上调用,以便当函数返回时,它可以将其弹回到指令指针(IP)并从那里继续。

为了解释,我简化了一些事情。

答案 2 :(得分:2)

当一个函数被调用时,调用函数中的正确返回地址被放置在某个地方,通常是堆栈,虽然标准没有强制要求,这用于存储返回地址的目的。

编译器有责任确保其调用约定除非出现问题(例如,stack overflow),否则被调用的函数知道如何返回调用函数。

答案 3 :(得分:1)

运行时使用一些称为“调用堆栈”的东西,它基本上保存了在调用函数返回后要调用的下一个语句的地址。因此,当进行函数调用并且在控制跳转到新指令地址之前,调用函数中的下一个指令地址被推送到堆栈。并且对于任何后续对任何函数的调用都会重复此过程。现在为什么只有一堆?因为有必要回到它停止的地步 - 这基本上是'先进先出'行为,而堆栈就是这样做的数据结构。在Visual Studio中调试程序时,您实际上可以查看此调用堆栈 - 有一个名为“调用堆栈”的单独窗口,它显示调用堆栈中放置的地址条目。