嗨,有人可以解释一下这段代码吗?
#include <stdio.h>
int main(){
void myfunc(int x){
printf (" [%d]",x);
printf ("M here 1\n");
if (x > 0) myfunc(--x);
printf ("M here 2\n");
printf (" %d,\n",x);
}
myfunc(5);
}
输出结果是:
[5]M here 1
[4]M here 1
[3]M here 1
[2]M here 1
[1]M here 1
[0]M here 1
0,M here 2 [0]
0,M here 2 [1]
1,M here 2 [2]
2,M here 2 [3]
3,M here 2 [4]
4,M here 2 [5]
然而,我被困在如何,
0,M here 2 [0]
0,M here 2 [1]
1,M here 2 [2]
2,M here 2 [3]
3,M here 2 [4]
4,M here 2 [5]
不应该停在
0,M here 2 [0]
答案 0 :(得分:2)
不应该停在
不,不应该。递归调用返回后,函数继续执行该行之后的行。
当输入为myfunc
时,让我们通过2
的借口。之后,您可以将其推断为更高的值。使用2
调用函数时,您会得到:
printf (" [%d]",2);
printf ("M here 1\n");
myfunc(1); // Since 2 > 0
printf ("M here 2\n");
printf (" %d,\n",1); // You get 1 here since x is decremented.
使用1
调用该函数时,您将获得
printf (" [%d]",1);
printf ("M here 1\n");
myfunc(0); // Since 1 > 0
printf ("M here 2\n");
printf (" %d,\n",0); // You get 0 here since x is decremented.
使用0
调用该函数时,您将获得
printf (" [%d]",0);
printf ("M here 1\n");
// No more recursion since the input is 0
printf ("M here 2\n");
printf (" %d,\n",0); // You get 0 here since x is NOT decremented.
现在,如果你压缩递归调用,你会得到:
printf (" [%d]",2);
printf ("M here 1\n");
printf (" [%d]",1);
printf ("M here 1\n");
printf (" [%d]",0);
printf ("M here 1\n");
printf ("M here 2\n");
printf (" %d,\n",0);
printf ("M here 2\n");
printf (" %d,\n",0);
printf ("M here 2\n");
printf (" %d,\n",1);
很容易理解为什么会产生输出:
[2]M here 1
[1]M here 1
[0]M here 1
M here 2
0,
M here 2
0,
M here 2
1,
答案 1 :(得分:1)
这是你的代码,我只更改了传递给main函数中myfunc
的参数并标记了不同的行,因此更容易解释会发生什么:
#include <stdio.h>
int main(){
void myfunc(int x){
printf (" [%d]",x); // [1]
printf ("M here 1\n"); // [2]
if (x > 0) // [3]
myfunc(--x); // [4]
printf ("M here 2\n"); // [5]
printf (" %d,\n",x); // [6]
}
myfunc(2); // [7]
}
以下是发生的事情。在执行代码行的第一列中,在中间列中,执行它的上下文,在最后一列中,在当前上下文中x
的值。
Context Value of x
[7] Call myfunc(2) Main function N/A
|
+-> [1] print 1st call to myfunc 2
[2] print 1st call 2
[3] x > 0 is true 1st call 2
[4] x := x - 1 1st call 1
[4] Call myfunc(x) 1st call 1
|
+-> [1] print 2nd call to myfunc 1
[2] print 2nd call 1
[3] x > 0 is true 2nd call 1
[4] x := x - 1 2nd call 0
[4] Call myfunc(x) 2nd call 0
|
+-> [1] print 3rd call to myfunc 0
[2] print 3rd call 0
[3] x > 0 is false 3rd call 0
[5] print 3rd call 0
[6] print 3rd call 0
Retun 3rd call 0
|
<-+
[5] print 2nd call to myfunc 0
[6] print 2nd call 0
Retun 2nd call 0
|
<-+
[5] print 1st call to myfunc 1
[6] print 1st call 1
Return 1st call
如果您使用相应的x值调用所有调用的打印件,则会得到:
[1] print 2
[2] print 2 > [2]M here 1
[1] print 1
[2] print 1 > [1]M here 1
[1] print 0
[2] print 0 > [0]M here 1
[5] print 0 > M here 2
[6] print 0 > 0,
[5] print 0 > M here 2
[6] print 0 > 0,
[5] print 1 > M here 2
[6] print 1 > 1,
在重复发生时,您必须记住,每次在内部调用函数时,在某个时刻,此调用将返回,并且以下语句将正常执行。构建/理解递归函数的一个好方法是看它不是一组“独立”处理的语句,而是将它看作是完成某项工作的整个指令。这样,如果您可以首先编写函数的规范,那么您就知道如何在其自身内部重用它以及它是否安全。