30

私はグーグルで検索しましたが、この単純な質問に対する答えが見つからないようです。

レガシーコードベースで作業していて(最近Linuxに移植され、新しいコンパイラにゆっくりと更新されています)、多くのことがわかります

int myfunction(...)
{
// no return...
}

関数の暗黙的な戻り型がintであることは知っていますが、戻り値が指定されていない場合の暗黙的な戻り値は何ですか。私はテストして0を取得しましたが、それはgccでのみです。このコンパイラは固有ですか、それとも標準で0に定義されていますか?

編集:2017年12月標準のより新しいバージョンを参照することに基づいて、受け入れられた回答を調整しました。

4

7 に答える 7

24

新約聖書で引用されている'89年の基準から:

関数の終わりから流れ出るのは、式のない戻りと同じです。いずれの場合も、戻り値は未定義です。

この標準は通常、既存の実装の現場での動作を表します。

于 2012-04-09T20:12:35.570 に答える
16

そのようなことは可能ですが、関数の戻り値が決して使用されないという前提の下でのみです。C11標準は、パラグラフ6.9.1で次のように述べています。

関数を終了する } に到達し、関数呼び出しの値が呼び出し元によって使用された場合、動作は未定義です。

(標準のAFAIRの以前のバージョンには同様の文言がありました)

そのため、そのような関数のすべての関数を関数に変換することをお勧めしますvoid。これにより、そのような関数のユーザーが戻り値を使用するように誘惑されることはありません。

于 2012-04-09T20:30:47.377 に答える
14

関数の戻り値の型が でなくても、return ステートメントは関数の最後で必須ではありませんvoid。診断は不要であり、未定義の動作ではありません。

例 (定義済みの動作):

int foo(void)
{
}

int main()
{
    foo();
}

ただし、戻り値の読み取りfooは未定義の動作です。

int bla = foo();  // undefined behavior

C標準から:

( C99、p.12 の 6.9.1) 「関数を終了する } に到達し、関数呼び出しの値が呼び出し元によって使用される場合、動作は未定義です。」

main関数は、ステートメント}main存在する場合と同等であるかのように、この規則の例外です。return 0;

( C99 ドラフト、p.13 の 5.1.2.2.3) ...関数}を終了するに到達するとmain、値 0 が返されます。

于 2012-04-09T20:32:10.027 に答える
9

これは単に未定義の動作です。リターン領域(たとえば、x86ファミリプロセッサでは通常eax / rax)を設定しない場合、関数の副作用によって最後に設定された値になります。

voidを返さないC++関数にはreturnステートメントが必須ですか?を参照してください。これは基本的にこの質問の複製です(C ++としてタグ付けされていることを除いて)。

于 2012-04-09T20:12:36.253 に答える
2

returnステートメントが一貫して値を返さない場合、関数は次のように変換され、次のように宣言されるのが最適voidです。

void myfunction(...)
{
    ...
    return;
    ...
}

関数にいくつかのステートメントreturn expr;といくつかのreturn;ステートメントがある場合、どちらがより良い動作であるかを決定し、それらを一貫させる必要があります — 常に値を返して型をそのままにするintか、値を決して返さずに型を に変更しvoidます

デフォルトの戻り値の型 (想定される戻り値の型)はもはや有効ではないためvoid、返すように変更された関数を宣言する必要があることに注意してください。staticint

于 2012-04-09T20:19:08.893 に答える
1

その関数では常にゼロである可能性がありますが、ほとんどのアーキテクチャ (確かに x86) では、return ステートメントは特定のレジスタの内容を、呼び出し元が取得して戻り関数として使用するスタック上の特定の場所に移動します。

return ステートメントは、渡された変数をその場所に配置して、異なる値になるようにします。特定の return ステートメントを配置しないという私の経験では、返されるものはかなりランダムであり、同じものであることに依存することはできません。

于 2012-04-09T20:13:55.850 に答える
0

戻り値の型がステートメントvoidを省略しない関数の未定義の動作であることは確かです。returnC99 には例外がありmainreturnステートメントが省略された場合、暗黙的に 0 を返すと想定されますが、これは他の関数には適用されません。

特定のプラットフォームとコンパイラの組み合わせで動作する場合がありますが、そのような仕様に依存するべきではありません。コードで何らかの未定義の動作を使用すると、移植できなくなります。ただし、レガシー コードで未定義の動作が見られるのはよくあることです。

于 2012-04-09T20:12:39.640 に答える