为什么这个递归函数有效?

时间:2016-04-12 07:23:40

标签: c++

所以我的一个朋友正在参加他的第一个CS课程,并提到他在他的第一个课程中使用递归。他发给我下面的代码。马上,我注意到他没有抓住他的递归调用的返回值,我认为它不起作用。但是他坚持认为它确实有效,所以我尝试了他的程序,令我惊讶的是它的功能完全符合预期。忽略这一事实,这是从A点到B点的愚蠢方式,为什么这甚至有效?

我正在玩他发给我的东西,并在if语句后添加cout。除此之外,第一块代码和第二块相同。

如果我为第一个节目输入以下内容,这就是我得到的内容......

  

输入一个数字:10

     

您输入了:10这是正确的吗? (是/否):N

     

输入一个数字:12

     

您输入了:12这是正确的吗? (是/否):Y

     

main()= 12

然后,如果我对第二个程序做同样的事情,这就是我得到的......

  

输入一个数字:10

     

您输入了:10这是正确的吗? (是/否):N

     

输入一个数字:12

     

您输入了:12这是正确的吗? (是/否):Y

     

main()= 6300096

发生了什么事?!

#include <iostream>
#include <cstring>
#include <cctype>

using namespace std;

int getNum() 
{
    cout << "Enter a Number: ";
    int x;
    cin >> x;
    cin.ignore(100, '\n');

    while(x < 0) {
        cout << "Please enter amount greater than 0: ";
        cin >> x;
        cin.ignore(100, '\n');
    }

    cout << "You entered: " << x << " Is this correct? (Y/N): ";
    char response;
    cin >> response;
    cin.ignore(100, '\n');

    if (response != 'Y') {
        getNum();
    } else {
        return x;
    }
}

int main() {

    cout << "\nmain() = " << getNum() << endl;

    return 0;
}

顶部和底部之间的唯一区别是if语句之后的cout语句。

#include <iostream>
#include <cstring>
#include <cctype>

using namespace std;

int getNum() 
{
    cout << "Enter a Number: ";
    int x;
    cin >> x;
    cin.ignore(100, '\n');

    while(x < 0) {
        cout << "Please enter amount greater than 0: ";
        cin >> x;
        cin.ignore(100, '\n');
    }

    cout << "You entered: " << x << " Is this correct? (Y/N): ";
    char response;
    cin >> response;
    cin.ignore(100, '\n');

    if (response != 'Y') {
        getNum();
    } else {
        return x;
    }
    cout << "returning... " << x;
}

int main() {

    cout << "\nmain() = " << getNum() << endl;

    return 0;
}

2 个答案:

答案 0 :(得分:6)

在机器代码级别,通常在特定的处理器寄存器中返回足够小的函数结果。

通过在return的某些调用中不执行getNum语句,正式代码具有未定义的行为,但可能会发生以下情况:

  1. getNum()被调用,用户回答N

  2. getNum()以递归方式调用,用户回答Y

  3. getNum()执行return x;。使用典型的C ++实现,将返回值放在寄存器中,让它称之为R.

  4. 执行返回getNum()(原始调用),现在通过函数结束执行返回,而不是return

  5. 调用代码按预期在寄存器R中找到值。

  6. 所以,它可以“起作用”。

    但它是正式的Undefined Behavior,以及其他一些编译器和/或选项,它可能无效。

答案 1 :(得分:2)

在C ++中,编译器没有彻底检查函数是否在没有return语句的情况下结束其流程,因为检查所有控制路径并不容易。此代码的行为未定义,实际发生的内容取决于调用约定。

我认为他们在return之前忘了getNum()。它会工作并且不会污染堆栈,因为如果尾递归优化。

这个代码对于第一个CS类来说很奇怪。