2016-04-12 13 views
1

私の友人は彼の最初のCSクラスの一つを取っていて、彼の最初のプログラムで再帰を使っていると言います。彼は私に以下のコードを送る。バットをオフにしてすぐに、私は彼が再帰呼び出しの戻り値をキャッチしていないことに気付きました。しかし、彼はそれが機能すると主張するので、私は彼のプログラムを試してみると、私の驚きには、それは期待どおりに機能します。これがA点からB点に向かうばかげた方法であるという事実を無視して、なぜこれは機能するのでしょうか?この再帰関数はなぜ機能しますか?

私が送ったもので遊んでいて、if文の後にcoutを追加しました。それ以外に、コードの最初のチャンクと2番目のチャンクは同じです。

I入力は最初のプログラムのために、以下の、ここで私が何を得るなら...

が番号を入力してください:10

あなたは入力された:10これは正しいですか? (Y/N):N

が番号を入力してください:12

あなたは、入力された:12は、この正しいですか? (Y/N):Y

メイン()= 12

そして、私は2番目のプログラムで同じことをすれば、その後、ここで私は何を得るのです...

入力してください番号:10

入力した:10これは間違いありませんか? (Y/N):N

が番号を入力してください:12

あなたは、入力された:12は、この正しいですか? (Y/N):Y

メイン()=何が起こっている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ステートメントです。 C++で

#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; 
} 
+3

'if(response!= 'Y')'では、getNum();を返すべきではありませんか?これを書くと、 'response!= 'Y''ならば何も返さないので、最初のプログラムが動くというのは主に運がいいです。 – tforgione

+1

はい、あなたは正しいですが、私は運の部分について尋ねています。 –

+0

あなたの質問が分かりませんでした。 – tforgione

答えて

6

マシンコードレベルでは、通常、特定のプロセッサレジスタに十分小さな関数結果が返されます。

正式にコードがgetNumのいくつかの呼び出しでreturn文を実行しないことにより、未定義の動作をしているが、何が起こるかは、おそらくこれです:

  1. getNum()は、ユーザがNに答える、と呼ばれています。

  2. getNum()は、再帰的にユーザー応答Yを呼び出します。

  3. getNum()return x;を実行します。典型的なC++の実装では、これはレジスタの戻り値を置く、のは、それを呼びましょうR.

  4. 実行は今、関数の終わり、無returnを通過実行によって返されgetNum()(元のコール)、までを返します。

  5. 呼び出しコードは、レジスタRの値を期待どおりに見つけます。

だから、それは“仕事”をすることができます。

しかし、それは正式に未定義の動作であり、他のコンパイラやオプションでは動作しない可能性があります。

+1

これはまた、 'cout <<"が返ってくるとうまくいかない理由を説明しています... "<< x;' - そのコード自体が "R"を使っています.... –

+0

@TonyD:ありがとう、ありがとう。 :) –

2

、コンパイラは徹底的に、それはすべての制御パスをチェックする簡単な作業ではありませんので、その関数がreturn文なしでその流れを終了チェックしません。このコードの動作は定義されていません。実際に発生するのは呼び出し規約に依存します。

returnの前に忘れてしまったと思います。getNum()より前です。テール再帰の最適化のためにスタックが汚染されることはありません。

このコードは最初のCSクラスでは奇妙です。

関連する問題