4

我试图了解如何在 C 中使用递归,但我不知道return它是如何工作的。

请考虑以下代码:

int     recur(int i)
{
    printf("recur: i = %d\n", i);
    if (i < 3)
    {
        recur(i + 1);
        return 10;
    }
    else if (i < 5)
        recur(i + 1);
    return i;
}

int     main(void)
{
    int     i = 0;
    i = recur(i);
    printf("i = %d\n", i);
    return 0;
}

输出是:

recur: i = 0
recur: i = 1
recur: i = 2
recur: i = 3
recur: i = 4
recur: i = 5
i = 10

最后一个返回, return i, 做什么?这段代码是否有意义?

4

4 回答 4

10

函数的递归调用不会影响返回值。只有在return递归函数的第一个实例中遇到的第一个会返回一个值给父函数。任何其他return遇到只会停止程序当前所在的函数实例。

因此,由于在 main 中使用参数 0 调用了该函数

int     i = 0;
i = recur(i);

第一次return见面位于if语句内部:

if (i < 3)
{
    recur(i + 1);
    return 10;
}

在这种情况下,recur函数在返回值之前被调用main。它将创建另一个实例,recur它会做一些事情,但在这个实例recur结束后,主实例recur将继续,在这种情况下,将返回 10 给函数main

要知道您的递归函数将返回main函数的内容,您可以简单地注释对函数新实例的所有调用:

int     recur(int i)
{
    if (i < 3)
    {
        //recur(i + 1);
        return 10;
    }
    else if (i < 5)
    {
        //recur(i + 1);
    }
    return i;
}

在这种情况下,程序将读取以下内容:

int     recur(int i)
{
    if (i < 3)
        return 10;
    return i;
}
于 2017-05-29T11:56:30.613 回答
3

我认为这是最容易理解的递归函数之一。

int pow(int n, int x)
{
    if (n != 1)
        return x * pow(n - 1, x)
    else 
        return x;
} 

来学习吧 pow(3, 2) : 2^3 = 2 * 2 * 2 = 8

第一次迭代: pow(3, 2) returns 2 * pow(2, 2)
第二次迭代: pow(2, 2) returns 2 * 2* pow(1, 2)
第三次迭代: n == 1 所以pow(1, 2) returns x = 2 * 2 * 2 = 8

i + 1递归函数在过程的步骤中返回对自身的调用。为了避免无限循环,你必须让 sur 你有一个 break 条件,这会导致返回到与 self-call 不同的东西。

于 2017-05-29T12:18:57.280 回答
0

您至少得到了一个有助于解释代码行为的答案。

我想在这里通过不同的附加路径提供帮助。两者共同为您提供不同的观点。
为此,我提供了一个通过检测增强的代码版本,它更详细地告诉您发生了什么。
这使您可以使用代码并进行观察,这将为您提供真正有用的答案。

笔记:

  • 这些for(c行仅用于提示性缩进;
    我选择不为此使用函数,感觉它使有趣的函数调用更加突出
  • 我添加了一个参数“嵌套”,它是为了
    • 制作(希望有用的)输出的一部分
    • 表明通常递归嵌套有一些影响
  • 我引入了一个局部变量“j”,
    以显示在大多数情况下 reutrn 值会发生什么

代码:

#include <stdio.h>

int     recur(int i, int nesting)
{   int c;
    for(c=0;c<nesting;c++) { printf(" ");}
    printf("recur[%d](%i)", nesting, i);
    if (i < 3)
    {   printf("i <3, calling recur[%d](%d)\n", nesting+1, i+1);
        recur(i + 1, nesting+1);
        for(c=0;c<nesting;c++) { printf(" ");}
        printf("returning 10 from recur[%d], with i==%d\n", nesting, i);
        return 10;
    }
    else if (i < 5)
    {
        int j=0;
        printf("i <5, calling recur[%d](%d)\n", nesting+1, i +1);
        j=recur(i + 1, nesting+1);
        for(c=0;c<nesting;c++) { printf(" ");}
        printf("ignored return value from recur[%d](%d) is %d", nesting+1, i+1, j);
    }

    printf("\n");
    for(c=0;c<nesting;c++) { printf(" ");}
    printf("returning i from recur[%d], with i==%d\n", nesting, i);
    return i;
}

int     main(void)
{
    int     i = 0;
    i = recur(i, 0);
    printf("the last return value did not get ignored: i = %d\n", i);
    return 0;
}

输出:

recur[0](0)i <3, calling recur[1](1)
  recur[1](1)i <3, calling recur[2](2)
    recur[2](2)i <3, calling recur[3](3)
      recur[3](3)i <5, calling recur[4](4)
        recur[4](4)i <5, calling recur[5](5)
          recur[5](5)
          returning i from recur[5], with i==5
        ignored return value from recur[5](5) is 5
        returning i from recur[4], with i==4
      ignored return value from recur[4](4) is 4
      returning i from recur[3], with i==3
    returning 10 from recur[2], with i==2
  returning 10 from recur[1], with i==1
returning 10 from recur[0], with i==0
the last return value did not get ignored: i = 10

注意:
当然recur[n](m)不是 C 语法。
它只是表示使用参数“m”在嵌套级别“n”上调用函数“recur”。
(特别是不要将“[]”与数组混淆,它们不存在。)

于 2017-05-29T12:34:17.923 回答
-1

return 0 是主函数的返回,而不是递归代码的返回。

于 2017-05-29T11:48:44.873 回答