递归如何在C中起作用?

时间:2011-03-30 22:40:00

标签: c recursion

我试图理解C中的递归是如何工作的。任何人都可以给我一个控制流的解释吗?

#include <stdio.h>
/* printd: print n in decimal */
void printd(int n)
{
  if (n < 0)
  {
    putchar('-');
    n = -n;
  }
  if (n / 10) printd(n / 10);
  putchar(n % 10 + '0');
}

int main()
{
  printd(123);
  return 0;
}

7 个答案:

答案 0 :(得分:19)

控制流看起来像这样(其中->是函数调用)

main()
 └─> printd(123)
      ├─> printd(12)
      │    ├─> printd(1)
      │    │    └─> putchar('1')
      │    └─> putchar('2')
      └─> putchar('3')

答案 1 :(得分:1)

Call printd(123)
    (123 / 10) != 0, so Call printd(12)
        (12 / 10) != 0, so Call printd(1)
            (1 / 10) == 0, so Call putchar "1"
        Call putchar "2"
    Call putchar "3"
return 0 (from main())

答案 2 :(得分:0)

通过将问题分解为2个较小的问题,您可以使用C(或任何其他编程语言)进行递归。

您的示例:打印一个数字可以在这两部分中打破

  1. 打印第一部分(如果存在)
  2. 打印最后一位数字
  3. 要打印“123”,更简单的问题是打印“12”(12123 / 10)并打印“3”。
    要打印“12”,更简单的问题是打印“1”(112 / 10)并打印“2”。
    要打印“1”,...只需打印“1”。

答案 3 :(得分:0)

#include <stdio.h>

#define putd(d) (printf("%d", d))

#define RECURSIVE

void rprint(int n)
{
#ifndef RECURSIVE
    int i = n < 0 ? -n : n;

    for (; i / 10; i /= 10)
        putd(i % 10);

    putd(i % 10);

    if (n < 0)
        putchar('-');
    /* Don't forget to reverse :D */
#else
    if (n < 0) {
         n = -n;
         putchar('-');
    }

    int i = n / 10;
    if (i)
        rprint(i);

    putd(n % 10);
#endif
}

int main()
{
    rprint(-321);
    return 0;
}

答案 4 :(得分:0)

递归适用于堆栈,即最后一次。

递归是一个使用不同参数调用自身的过程,直到达到基本条件。执行过多的递归调用时会发生堆栈溢出。

答案 5 :(得分:0)

要了解递归,您需要了解存储模型。虽然存在多种变体,基本上是“自动”存储,但是用于包含自动变量,参数,编译器温度和呼叫/返回信息的存储被安排为“堆栈”。这是一个存储结构,从进程存储中的某个位置开始,并在调用过程时“增加”“向上”(增加地址)或“向下”(减少地址)。

有人可能会从一些变量开始:

00 -- Variable A -- 27
01 -- Variable B -- 45

然后我们决定调用过程X,因此我们生成一个参数A + B:

02 -- Parameter -- 72

我们需要保存我们想要控制返回的位置。说指令104是呼叫,所以我们将105作为返回地址:

03 -- Return address -- 105

我们还需要保存上面“堆栈框架”的大小 - 四个字,5个框架大小本身:

04 -- Frame size -- 5

现在我们开始在X中执行。它需要一个变量C:

05 -- Variable C -- 123

它需要引用参数。但它是如何做到的呢?好吧,在进入时,堆栈指针被设置为指向X的“堆栈帧”的“底部”。我们可以让“底部”成为几个地方中的任何一个,但让它成为X框架中的第一个变量。

05 -- Variable C -- 123  <=== (Stack frame pointer = 5)

但是我们仍然需要引用参数。我们知道“我们的帧”下面(堆栈帧指针所指向的位置)是(按递减的地址顺序)帧大小,返回地址,然后是我们的参数。因此,如果我们从5中减去3(对于这3个值),我们得到2,这是参数的位置。

注意,此时我们并不关心我们的帧指针是5还是55555 - 我们只是减去参考参数,添加引用我们的局部变量。如果我们想要进行调用,我们就像第一次调用那样“堆栈”参数,返回地址和帧大小。我们可以在通话后跟注,然后继续“推”堆栈帧。

要返回我们,请将帧大小和返回地址加载到寄存器中。从堆栈帧指针中减去帧大小,并将返回地址放入指令计数器,然后我们回到调用过程中。

现在这是一种过度简化,有许多不同的方法来处理堆栈帧指针,参数传递和跟踪帧大小。但基本知识无论如何都适用。

答案 6 :(得分:0)

enter code here




main()
{print f ("stat");
main();
print f ("end")  ;
}

在此处输入代码

main()
{int n, res;
pf("enter n value");
sf("%d",&n);

=fact(n);
}
int fact(int n)
{int res;
if(n==0)
{
res=1;
}
else
{
res = n*fact (n-1);
}
return res;
}