我在使用c和python进行编程时使用递归来解决这个问题,并且我猜测它在许多其他语言中使用过,但编译器如何实际解释递归函数?它如何在其自己的定义中使用该功能?
答案 0 :(得分:5)
但编译器如何实际解释递归函数?它如何在其自己的定义中使用该功能?
要理解这一点,您只需了解编译器如何解释函数。对于C,该函数只是一个符号,或指向内存中入口地址的指针。直观但不严格的是,函数调用将编译为这样的汇编指令:
CALL address_of_function
请参阅?编译器不需要知道函数是否是递归的。它只是让CPU跳转到函数入口的地址并继续执行指令。
这就是为什么我们可以使用该功能,即使它的定义没有完成。编译器只需知道起始地址或符号,然后它就会知道跳转的位置。函数的主体可以在以后生成。
但是,您可能想知道 Tail Recursion ,这是函数式编程语言中常见的一种特殊情况。 "尾部递归"表示递归函数调用是函数定义中的最后一个语句。正如@ paulsm4所提到的,在调用函数时,编译器需要将上下文和参数推送到堆栈中,然后恢复上下文并从中获取返回值。因此,如果你的函数调用自身然后调用它自己......,那么在内存耗尽之前,堆栈会太深。但是如果函数调用是函数定义中的最后一个语句,那么就没有必要在堆栈中保存上下文,我们只能覆盖它。因此,即使函数无限地调用自身,堆栈也不会溢出。
答案 1 :(得分:3)
它完全依赖于编译器......但是大多数语言中的大多数编译器都通过使用堆栈来实现递归。
编译器生成推送程序参数的代码,保存当前堆栈和帧指针,然后简单地调用相同的函数(使用新更新的堆栈)。
这是一篇非常好的文章:Understanding the stack