为什么递归函数调用需要将值返回给调用函数?

时间:2017-12-22 04:50:12

标签: c visual-studio recursion return

在以下递归函数中,

int subtractByOne(int num) {
    printf("%d\n", num);
    if (num == 0)
        return 0;
    return subtractByOne(num - 1);
}

为什么最终的回归必要?根据我的理解,基本情况将始终停止递归,并且当控制到达函数的末尾时(在递归调用之后),函数将控制转移给任何调用它而不返回。

我对堆栈帧和返回地址的了解很少,但堆栈应该接收一个独立于实际返回关键字的返回地址,不是吗?

Visual Studio 2015会发出有关控制路径的警告,我理解这一点。但是,在编程课程中,分级器的IDE不会编译类似的代码,教授评论代码是不正确的,而不仅仅是不好的练习。我当时修改了代码,但从未理解为什么它不正确。

4 个答案:

答案 0 :(得分:6)

函数定义表示它将返回一个整数。如果不放置最后一个返回,则只有基本情况将返回值0并将控制转移到前一个(调用者)函数,但不会发生其他返回。

在这种情况下,您可能不需要返回值,因此您可以在函数定义中使用void作为return,并完全取消所有返回值,但在许多情况下,您将需要返回。一个这样简单的例子是计算1 ... n整数的总和如下:

int sum(int n)
{
   if(n==0)
       return 0;
   return n + sum(n-1);
}

答案 1 :(得分:2)

在你的例子中,它可以正常工作。但是,如果函数声明声明函数应该返回值并且return语句是有条件的,编译器将会并且应该警告您。编译器不知道它会起作用。但是,如果编译器抛出错误,那听起来很奇怪。

完全没有必要使用return语句来实现递归。这是一个例子。

esc --> :wq

答案 2 :(得分:0)

  

为什么递归函数调用需要将值返回给调用函数?

简答:递归函数不必返回值

所有函数 - 递归与否 - 都有一个或多个returnreturn可能包含也可能不包含值。您可以决定何时编写该功能。所有显式编写的return语句都必须返回正确的类型。

但是,在函数结束时省略返回是合法的(但不好的做法)。但仅当返回值从未使用

所以下面的代码是合法的:

int subtractByOne(int num) {
    printf("%d\n", num);
    if (num == 0)
        return 0;
    subtractByOne(num - 1);
}

subtractByOne(42);

但是,下面的代码具有未定义的行为,因为使用了返回值并且函数在函数末尾没有返回值:

int subtractByOne(int num) {
    printf("%d\n", num);
    if (num == 0)
        return 0;
    subtractByOne(num - 1);
}

int a;
a = subtractByOne(42);  // Undefined behavior !
printf("%d", a);

正如您所看到的,可以以合法的方式使用相同的功能,但也会导致导致未定义的行为。 因此即使它是合法的,省略非void函数的return语句也是一个坏主意。换句话说 - 总是在非void函数中包含return语句。

BTW - 总是以高警告级别编译,以便编译器告诉您是否忘记了return语句。

您课程中失败的编译器可能会对此严格,因此会警告您,您的代码很糟糕(但并非违法)。

编写函数的更好方法是使其成为void函数:

void subtractByOne(int num) {
    printf("%d\n", num);
    if (num == 0)
        return;
    subtractByOne(num - 1);
}

答案 3 :(得分:0)

  

为什么最终的回归必要?从我的理解,基础   case将始终停止递归,并在控件到达结束时   该函数(在递归调用之后)将转移该函数   控制任何人在没有返回的情况下调用它。

您设计subtractByOne以返回int(这是其签名),然后您必须在每次通话时返回int类型的值。

  

我对堆栈帧和返回地址的了解很少,但是   stack应该接收一个独立于实际返回的返回地址   关键字,没有?

是的,代表您“自动”管理返回地址,这就是为什么显式使用return不需要返回调用者,规则就是如果您只是让指令流到达终点然后发出一个返回调用者的函数块。 return关键字用于从其他点返回,或将值发送回调用者

  

实践。我当时修复了代码,但从未理解为什么   是不正确的。

如果您没有向我们展示错误的代码,那么我们无法解释原因。

现在,

int subtractByOne(int num) {
    printf("%d\n", num);
    if (num == 0)
        return 0;
    return subtractByOne(num - 1);
}

虽然正确不是很有用,因为任何具有正值的调用都会得到0作为回报。