1

私はそれが機能しないと確信していたこのCコードを持っていますが、それは機能します。

#include <stdio.h>

int* find (int* a, int val) {
    if (*a == val)
        return a;
    else
        find(a+1, val);
}

int main() {
    int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int *b;

    b = find(a, 7);

    printf("%d\n", *b);

    return 0;
}

もちろん、find関数のelseブランチ内にreturnステートメントがないため、gccから警告が表示されます。ただし、完全に機能します。

なぜこれが起こるのですか?再帰関数を介してintを返すことをどのように知るのですか?もちろん、最後の呼び出しはintを返しますが、私はそれをvoidコンテキストで呼び出しています。

4

4 に答える 4

7

このコードは有効なCコードではなく、そのようなコードの動作は定義されていません。

これが機能する理由の1つは、最後の呼び出しの後に操作がないfindために、再帰呼び出しの戻り値が戻りレジスター(おそらくeax)にとどまる可能性があるためです。

しかし、繰り返しますが、動作は未定義です。

于 2013-02-07T14:31:58.357 に答える
3

これは機能しているようですが、未定義の動作です。特定の実装/プラットフォームbで、から返された最新の値を取得することがありますfind。ただし、別の実装/プラットフォームでは、これもクラッシュする可能性があります。

于 2013-02-07T14:31:15.230 に答える
2

findあなたが代わりに書くつもりだったと仮定するとtrova(私はイタリア語を学ぶことがいつか役に立つことを知っていました:)、答えはこれが完全に機能しないということです。未定義の動作により、純粋に偶然に「機能」します。

ほとんどの場合、最も深い再帰呼び出しは戻り値をあるレジスターにプッシュしますが、上位レベルの呼び出しにはreturnステートメントがないため、このレジスターには触れません。呼び出し元がそのレジスターを検査すると、最も深い呼び出しの戻り値が返されます。まだそこにあります。ただし、これに頼ることはできません。

于 2013-02-07T14:30:50.083 に答える
-1

参照が見つかりませんが、数年前から、GCCでは(CPUに割り当てられた)戻り値レジスタが常に最後の戻り値を持っていたので、ある値を計算して値なしで返す場合、前の値は持続します。この「機能」を使用するのは悪い習慣のようです。

多分また見る

http://stackoverflow.com/questions/1610030/why-can-you-return-from-a-non-void-function-without-returning-a-value-without-pr

C:値が指定されていない場合のデフォルトの戻り値?

つまり、Uniballer 2012年6月15日01:44関数宣言で実行しようとしていることを関数で実行しなかったため、動作はC言語では定義されていません。実際には、x86では、関数の値は、戻り時にレジスタeaxにあるものになります。

于 2013-02-07T15:13:09.653 に答える