私はグーグルで検索しましたが、この単純な質問に対する答えが見つからないようです。
レガシーコードベースで作業していて(最近Linuxに移植され、新しいコンパイラにゆっくりと更新されています)、
int myfunction(...)
{
// no return...
}
関数の暗黙の戻り値の型がintであることは知っていますが、戻り値が指定されていない場合の暗黙の戻り値は何ですか。私はテストして0を取得しましたが、それはgccでのみです。このコンパイラは固有ですか、それとも標準で0に定義されていますか?
編集:2017年12月標準のより新しいバージョンを参照することに基づいて、受け入れられた回答を調整しました。
そのようなことは可能ですが、関数の戻り値が決して使用されないという仮定の下でのみです。 C11標準は6.9.1項で次のように述べています。
関数を終了する}に到達し、関数呼び出しの値が呼び出し元によって使用される場合、動作は未定義です。
(標準の以前のバージョンのAFAIRにも同様の表現がありました)
したがって、その種のすべての関数をvoid
関数に変換することをお勧めします。そうすれば、そのような関数のユーザーが戻り値を使用したくなることはありません。
新約聖書で引用されている'89標準から:
関数の終わりから流れ出るのは、式のない戻りと同じです。いずれの場合も、戻り値は未定義です。
この標準は通常、既存の実装の現場での動作を表します。
それは単に未定義の振る舞いです。戻り領域にデータを入力しない場合(たとえば、通常は x86ファミリプロセッサではeax/rax )、関数の副作用によって最後に設定された値になります。
voidを返さないC++関数にはreturnステートメントが必須ですか? これは基本的にこの質問の複製です(C++としてタグ付けされていることを除いて)。
関数の戻り値の型がvoid
でなくても、関数の最後でreturnステートメントが必須になることはありません。診断は不要であり、未定義の動作ではありません。
例(定義された動作):
int foo(void)
{
}
int main()
{
foo();
}
ただし、foo
の戻り値の読み取りは未定義の動作です。
int bla = foo(); // undefined behavior
C標準から:
(C99、6.9.1p12)「関数を終了する}に到達し、関数呼び出しの値が呼び出し元によって使用される場合、動作は未定義です。」
main
関数はこのルールの例外です。main
で}
に到達した場合は、return 0;
ステートメントがあった場合と同等です。
return
ステートメントが一貫して値を返さない場合、関数はvoid
に変換され、次のように宣言されるのが最適です。
void myfunction(...)
{
...
return;
...
}
関数にいくつかのreturn expr;
ステートメントといくつかのreturn;
ステートメントがある場合は、どちらがより良い動作であるかを判断し、それらを一貫させる必要があります。常に値を返し、型をint
のままにするか、値を返さず、タイプをvoid
に変更しないでください。
void
のデフォルトの戻り値の型(想定される戻り値の型)がなくなったため、static
を返すように変更された関数を宣言する必要があることに注意してください(それらがint
であり、単一のソースファイルに隠されている場合を除きます)。有効です。
その関数では常にゼロになる可能性がありますが、ほとんどのアーキテクチャ(確かにx86)では、returnステートメントは、特定のレジスタの内容を、呼び出し元が取得してreturn関数として使用するスタック上の特定の場所に移動します。
Returnステートメントは、渡された変数をその場所に配置して、別の値になるようにします。特定のreturnステートメントを配置しないという私の経験では、返されるものはかなりランダムであり、同じものであると信頼することはできません。
戻り値の型がvoid
でない関数の場合、return
ステートメントを省略することは未定義の動作であると確信しています。 C99では、main
の例外があり、return
ステートメントが省略された場合、暗黙的に0を返すと見なされますが、これは他の関数には適用されません。
特定のプラットフォーム/コンパイラの組み合わせで動作する可能性がありますが、そのような詳細に依存しないでください。コードで未定義の動作を使用すると、移植できなくなります。ただし、レガシーコードで未定義の動作が見られるのはよくあることです。