【问题标题】:When we call a function recursively,does it involve a single call stack or one for each invocation of the function?当我们递归调用一个函数时,它是涉及一个调用堆栈还是每次调用该函数都涉及一个调用堆栈?
【发布时间】:2013-05-06 11:35:58
【问题描述】:

当在下面的代码中我从main() 调用函数fact() 时,这个fact() 的调用是否涉及fact() 的单个调用堆栈,或者由于fact() 本质上是递归的,它将涉及一个每次递归调用fact() 时都有单独的调用堆栈吗?我是递归的新手,对此一无所知。

#include<stdio.h>

int fact(int);

int main(void)
{
 int a=8;
 printf("The factorial of 8 is %d",fact(a));
}

int fact(int a)
{ 
    if(a==1)
    return 1;
    return a*fact(a-1);
}

【问题讨论】:

    标签: c recursion callstack


    【解决方案1】:

    只有一个调用栈(除非我们处理线程)。它从main 到当前最后一次调用是什么。对任何函数的每次调用都会在堆栈上形成一个“堆栈帧”,其中包含函数的参数、返回时返回的返回地址以及函数内的任何局部变量。

    正如一些答案中提到的,在某些情况下,编译器会在优化过程中消除递归。

    【讨论】:

      【解决方案2】:

      编译所有警告和调试信息(即在 Linux 上使用 gcc -Wall -g)然后使用调试器(在 Linux 上使用gdb)执行(step 命令到gdb)并显示回溯(bt )。

      只有一个调用栈(每个线程),但一个调用栈包含多个调用帧。

      当机器调用一个函数时,一个新的栈帧被安装(推送)到调用栈上。当该函数返回时,当前(最顶层)的调用框架被移除(弹出)。

      在维基百科上了解call stacks。另请阅读tail calls。

      【讨论】:

      • 我在 Win XP 中使用 CodeBlocks 并通过 GUI 编译。
      • 所以学习如何使用调试信息进行编译以及如何启动调试器。
      • 请用简单的语言陈述您的答案。您的意思是每个函数调用只有一个调用堆栈,即8次?什么是调用帧?
      • 请点击我给你的链接。
      • 这是我找到的链接。它更有帮助,可以直接回答问题programmerinterview.com/index.php/recursion/…
      【解决方案3】:

      对函数的每次调用都会保留堆栈上的内存空间,因此无论是否是递归调用,堆栈上总是有不同的空间,以避免在调用其他函数之间重叠其他状态。

      【讨论】:

      • 一些编译器能够进行尾调用优化....(但 OP 发布的代码不是尾递归的,因此它们不会使其成为尾调用)
      猜你喜欢
      • 2017-07-18
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2019-08-07
      • 2017-02-18
      • 1970-01-01
      • 1970-01-01
      • 2013-10-12
      相关资源
      最近更新 更多