2017-09-28 8 views
1

このコードは動作しますが、ここでは関数を再帰的に呼び出す際にreturnを使用しませんでした。それは私がPythonで同じコードを記述する場合、このコードはどれも(私が条件ならば値は内部のreturn文から返されるべきだと思う)ここでは再帰で戻り値を使用する

def gcd(a, b): 
    if b == 0: 
     return a 
    gcd(b, a % b) 

はこのコードを作らないために返し、正しい出力に

int gcd(int a, int b) 
{ 
    if(b == 0) 
     return a; 
    gcd(b, a % b); 
} 

を与えるが、仕事、私は返信を追加する必要があります

def gcd(a, b): 
    if b == 0: 
     return a 
    return gcd(b, a % b) 

なぜですか? CとPythonのコード実行の違いは何ですか?再帰的に呼び出すときに余分な戻り値を追加すると、C言語のコードも動作しますが、なぜそれはエラーをスローしませんか?

+3

として行方不明のリターンパスを扱います。 –

+1

プログラミングの第一のルール:これまで実行したたびに正しい結果が得られたからといって、プログラムが正しいとは限りません。あなたは最初のケースでは幸運なことがあります。最初のアキュムレータ(これはx86の場合は 'ax')に1つの' int'値が返され、全てのリターンコールが返される 'ax'の結果をすべての再帰が渡すと判断する' return a ' (あなたの 'gcd'再帰呼び出しがあなたがやる最後のものですから)変更されません。技術的には、明確に定義された動作であるためには、 'return gcd(b、a%b)'が必要です。 – lurker

+0

[Pythonでの再帰の基礎](https://stackoverflow.com/q/30214531/2823755)、SO Q&A @EugeneSh。 – wwii

答えて

7

なぜですか?偽の仮定。ちなみに、これはPythonに関する質問ではなく、約Cです。

あなたのCコードはです。です。 を使用するため、実際には制御パスでreturnステートメントを使用しない関数呼び出しの戻り値があるため、undefined behaviourがあります。あなたのコンパイラは、正しいオプション/設定でコンパイルすると、おそらくこれについて警告していたでしょう。私。これは、Cプログラムをコンパイルする方法ではありません。

% gcc -c 123.c 

代わりに、あなたは、すべての警告を有効にエラーにそれらを作ります。例えば

% gcc -c 123.c -Wall -Wextra -Werror -pedantic 
123.c: In function ‘gcd’: 
123.c:6:1: error: control reaches end of non-void function [-Werror=return-type] 
} 
^ 
cc1: all warnings being treated as errors 

GCC -Wall-Wextra-Werrorにと -pedanticは残念ながら、不正なコードのすべての種類は、Cコンパイラが本当に必要以上にデフォルトでは、より寛容であることを意味し、周りにあります。別の問題は、Cで return文を省略しても間違っていないことです。ガベージリターン値を使用するだけです。

PythonにはCのような未定義の動作がありませんので、return文を省略すると暗黙的にNoneが返され、壊れたコードが動作したように見えるランダムなガベージが取得されません。


より正確な関数定義を使用すると、これは常に負の数に対して正しく働くだろうという考えを取得しないように

int gcd(int a, int b) 
{ 
    if(b == 0) 
     return a; 
    return gcd(b, a % b); 
} 

は、しかし、おそらくこれらの引数はunsigned intのあるべきだろう。

+0

しかし、値の関数 '返す' '返す'ステートメントではなぜ私たちは再帰呼び出しの前にリターンを提供する必要がありますか? –

+1

@SHASHANKSHEKHARこれは、タマネギの*最奥のレイヤーだけの戻り値を与えるからです...ちなみにここではカメです...すべて終わっていますが、最外層はそれを返す必要はありません。 –

2

Cのコードには未定義の動作があり、2番目のコードパス(再帰呼び出し)にはreturnステートメントがありません。あなたは戻り値が常に同じレジスタに保存され、上書きされないことは幸運ですが、保証されておらず、あなたは迷惑になるかもしれません。

Pythonは明示的に非void型関数のすべての実行パスが値を返さなければCでreturn None

関連する問題