我试图理解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;
}
答案 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(或任何其他编程语言)进行递归。
您的示例:打印一个数字可以在这两部分中打破
要打印“123”,更简单的问题是打印“12”(12
是123 / 10
)并打印“3”。
要打印“12”,更简单的问题是打印“1”(1
是12 / 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;
}