即使经过一定的循环后,递归如何保持价值

时间:2019-01-31 12:06:13

标签: c recursion

有人可以解释一下该程序的执行情况。 输出是: 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);
}

4 个答案:

答案 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内的变量foox内的变量bar以外的另一个变量。他们唯一的关系是,x内的fooxbar值的副本进行了初始化。无论您在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 ()将打印出5fun2 () 6fun3() 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");
}