有人可以解释一下该程序的执行情况。 输出是: 1个 2 3 4 3 2 1
函数最后如何保留值3,2,1
main(){
int h=0;
g(h);
}
g(int n){
n++;
printf("%d\n",n);
if (n ==4)return 88;
g(n);
printf("%d\n",n);
}
答案 0 :(得分:4)
之所以得到上面的输出,是因为在代码的第8行,您递归地调用了函数agian,因此第8行之后的其余代码被保存在内存中的调用堆栈中。因此,当您获得输出1 2 3 4时,将执行剩下的(在调用堆栈中)剩余的代码,因此您将获得此输出。
下面是程序的调用堆栈
当n = 0时,堆栈将放置1
|___|
|___|
|_1_|
当n = 1时,堆栈将放置2
|___|
|_2_|
|_1_|
当n = 2时,堆栈将放置3
|_3_|
|_2_|
|_1_|
当n = 4时,堆栈将不会放置任何东西,因为它遇到return语句
现在,我们的堆栈中有一些值
,因此程序开始弹出堆栈中的最高值(此处n = 3),并从中断处继续执行(即,将打印该值),此过程将继续进行直到堆栈为空。
注意:您可以观看此视频,以更有效地了解递归https://www.youtube.com/watch?v=Mv9NEXX1VHc
答案 1 :(得分:2)
g(int n){
n++;
printf("%d\n",n); // n=1 print 1 & call g(n) with 1 now g(1) make its own n=2 print 2 & call g(2)
//... print 3 & call g(3) becomes 4 print 4 return 88
if (n ==4)return 88;
g(n);
// now after the return we get back to the 3rd call that called g(3)
//so it print 3 at the end 3 ends
//we go back to the one that called g(2) so we print 2 at the end... & same for 1
printf("%d\n",n);
}
答案 2 :(得分:2)
在C中,函数参数充当函数内部的局部变量。进一步的C使用按值调用,这意味着调用方用作参数的变量的值被复制到函数参数变量。因此,这两个变量是完全独立的变量。
考虑以下代码:
void foo(int x)
{
x++;
printf("%d", x);
}
void bar(int y)
{
y++;
printf("%d ", y);
foo(y);
printf("%d", y);
}
bar(0);
这将输出“ 1 2 1”
大多数人发现,对x
的更改显然不会改变y
。它们是两个不同的变量。因此,这不足为奇。
如果我们更改代码以对变量使用相同的名称,例如:
void foo(int x)
{
x++;
printf("%d", x);
}
void bar(int x)
{
x++;
printf("%d ", x);
foo(x);
printf("%d", x);
}
bar(0);
输出仍为“ 1 2 1”
仅因为x
内的变量foo
是x
内的变量bar
以外的另一个变量。他们唯一的关系是,x
内的foo
用x
内bar
值的副本进行了初始化。无论您在x
内对foo
进行何种更改,它都将/无法在x
内更改bar
。
递归完全相同。每个函数调用都会创建自己的变量n
-完全独立于先前调用中的n
变量。
大多数实现都使用堆栈来实现此功能。搜索“堆栈框架”以获取更多信息。另见 Explain the concept of a stack frame in a nutshell
答案 3 :(得分:1)
您可以阅读上述答案,它们的确不错,但是这是让您摆脱困境的另一种方法。最简单的答案与调用任何函数时调用方函数保留其值的方式相同。例如,如果您有:
int main (void) {
int a = 5;
fun1 (a);
}
void fun1 (a) {
fun2 (a);
printf("%d\n", a); // output would be 5
}
void fun2 (int a) {
a+=1;
fun3 (a);
printf("%d\n", a);
}
void fun3 (int a) {
a+=1;
printf("%d\n", a);
}
因此fun1 ()
将打印出5
,fun2 ()
6
和fun3()
7
。从调用者和被调用函数的角度来看,递归函数与上面类似,而不是使用不同名称调用函数,而是使用相同名称调用函数,或者换句话说,它正在调用自身。
看下面的代码:
void recFun (int a) {
if (a > 6)
printf("%d\n", a);
recFun (a + 1);
printf("%d\n");
}
当我在学校的时候,有些人会改写成下面的内容(在纸上,如果您尝试编译它,当然会对您大喊大叫):
void recFun (int a) {
recFun (a + 1);
printf("%d\n");
}
void recFun (int a) {
recFun (a + 1);
printf("%d\n");
}
void recFun (int a) {
printf("%d\n");
}