回答:
実際には 違いがありますが、微妙です。C ++にはより多くの影響がありますが、違いは重要です。
で呼び出すreturn
とmain()
、ローカルスコープのオブジェクトに対してデストラクタが呼び出されます。私が呼び出した場合exit()
、何のデストラクタは私のローカルスコープのオブジェクトのために呼び出されません!もう一度読んでください。exit()
戻りません。つまり、私がそれを一度呼ぶと、「背中はありません」ということはありません。その関数で作成したオブジェクトは破棄されません。多くの場合、これは影響を与えませんが、ファイルを閉じるなど、場合によっては影響を及ぼします(すべてのデータをディスクにフラッシュする必要がありますか?)。
static
を呼び出してもオブジェクトはクリーンアップされることに注意してくださいexit()
。最後に、を使用した場合abort()
、オブジェクトは破棄されないことに注意してください。つまり、グローバルオブジェクト、静的オブジェクト、ローカルオブジェクトのデストラクタは呼び出されません。
リターンよりも出口を優先する場合は、慎重に進んでください。
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
thread_local
オブジェクトのデストラクタが呼び出されます。他のローカルオブジェクトのデストラクタはまだ呼び出されません。ideone.com/Y6Dh3f
exit()
ファイルを完全に閉じるという問題は実際には間違っています。データがフラッシュされない可能性があるのは、その逆の場合のみです。つまり、return
from main()
を使用し、呼び出しが行われたsetbuf()
場合setvbuf()
、またはmain()
(以下のRの回答で説明されているように)自動ストレージとして宣言されたバッファーを使用した場合です。この質問にCとC ++の両方のタグが付けられているのは本当に残念です(そしてコーディングスタイル-スタイルの問題ではありません!)。
もう1つの違い
exit
は、標準ライブラリ関数であるため、ヘッダーを含めて標準ライブラリとリンクする必要があることです。(C ++で)説明すると、これは有効なプログラムです。
int main() { return 0; }
ただし、使用exit
するにはインクルードが必要です。
#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }
さらに、これは追加の仮定を追加します:からの呼び出しexit
にmain
はゼロを返すのと同じ副作用があります。他の人が指摘したように、これはどのような実行可能ファイルを作成するか(つまり、誰がを呼び出すかmain
)に依存します。Cランタイムを使用するアプリをコーディングしていますか?Mayaプラグイン?Windowsサービス?ドライバー?それぞれのケースで、がとexit
同等かどうかを調べるための調査が必要になりますreturn
。IMHOを本当に意味するexit
ときに使用すると、コードがさらに混乱します。OTOH、本当にそういう意味なら、是非使ってください。 return
exit
そこ好む少なくとも一つの理由は、exit
あなたのいずれかの場合:atexit
ハンドラに自動ストレージ期間のデータを参照main
、またはあなたが使用している場合setvbuf
やsetbuf
、標準の一つに割り当てることで自動ストレージ期間のバッファをストリームmain
、その後から戻って、main
生成します未定義の動作exit
ですが、呼び出しは有効です。
別の潜在的な使用法(ただし、通常はおもちゃのプログラム用に予約されています)は、を再帰的に呼び出してプログラムを終了することですmain
。
return
の標準プロトタイプmain()
はを返すと言っているので、私は常に使用していint
ます。
main
とはいえ、一部のバージョンの標準は特別な扱いをしており、明示的なreturn
ステートメントがない場合は0を返すと想定しています。次のコードがあるとします:
int foo() {}
int main(int argc, char *argv[]) {}
G ++は警告を生成するだけでfoo()
、不足しているからの戻り値を無視しmain
ます:
% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function
return
からといって、その実行を終了するために使用する必要があるわけではありません。呼び出しexit()
は、関数の実行を終了するための有効な方法であり、必要な場合もあります。実際、私や他の人が他の場所で説明したように、exit()
から呼び出しても、main()
プロセス全体を終了するというはるかに明確な意図が伝えられ、プロセスが終了するまで自動ストレージが保持され、コードの将来のリファクタリング中のメンテナンスが容易になります。したがって、C がプロセスを終了することを意図してreturn
in を使用main()
することは、間違いなく悪い習慣です。
プログラムが実際に終了する前に自動ストレージが再利用されるのを回避するために、exit()の使用についてR.のコメントを強く示しますmain()
。のreturn X;
ステートメントは、main()
への呼び出しと正確に同じではありません。戻り時にexit(X);
動的なストレージがmain()
消失するmain()
ためexit()
ですが、代わりにへの呼び出しが行われた場合には消失しません。
さらに、CまたはCのような言語では、return
ステートメントは、実行が呼び出し元の関数で継続することを読者に強く示唆しています。この実行の継続は、通常、main()
関数を呼び出したCスタートアップルーチンを数えると技術的に当てはまりますが、そうではありません。プロセスを終了するつもりであるときに正確に何を意味するか。
結局のところ、あなたは除いて、他の機能の中から、あなたのプログラムを終了したい場合はmain()
、あなたがしなければならない電話をexit()
。main()
同様に一貫してそうすることで、コードがはるかに読みやすくなり、誰でもコードをリファクタリングするのがはるかに簡単になります。つまりmain()
、他の関数からにコピーされたコードは、呼び出しでreturn
あるはずの偶発的なステートメントが原因で誤動作することはありませんexit()
。
したがって、これらのすべてのポイントを組み合わせると、少なくともCでは、ステートメントを使用してでプログラムを終了するのは悪い習慣であるという結論return
になりmain()
ます。
exit()
、一般的には避けることをお勧めしますが、特定の状況でa throw
またはabort()
代替案が機能しない場合は使用してください。ただし、特にexit()
mainでの使用は避け、一般的な方法として、代わりにmainでreturnを使用してください。
exit()は 'return'が行わない特別なことをしますか?
まれなプラットフォーム用の一部のコンパイラーでは、exit()
その引数をプログラムの終了値に変換する場合がありますが、returnからmain()
は、変換せずに値を直接ホスト環境に渡す場合があります。
標準では、これらのケースで同一の動作が必要です(具体的には、int
互換性のあるものを返すことは、その値でmain()
呼び出すことと同等である必要があるexit()
と述べています)。問題は、OSごとに終了値を解釈するための規則が異なることです。多くの(多くの)システムでは、0は成功を意味し、それ以外は失敗を意味します。しかし、たとえばVMSでは、奇数値は成功を意味し、偶数値は失敗を意味します。から0を返した場合main()
、VMSユーザーはアクセス違反について厄介なメッセージを表示します。実際にはアクセス違反はありませんでした。これは単にエラーコード0に関連付けられた標準メッセージです。
その後、ANSIは、一緒に来て、祝福されたEXIT_SUCCESS
とEXIT_FAILURE
引数として、あなたはに渡すことができますexit()
。また、標準では、exit(0)
はと同じように動作する必要があるためexit(EXIT_SUCCESS)
、ほとんどの実装はに定義さEXIT_SUCCESS
れてい0
ます。
したがって、この標準では、たまたま値0のエラーコードを返す標準的な方法がないため、VMSでバインドされます。
したがって、1990年代初頭のVAX / VMS Cコンパイラは、からの戻り値を解釈せずmain()
、単にホスト環境に任意の値を返しました。しかし、それを使用exit()
した場合、標準が要求することを実行します。つまり、成功コードと一般的な失敗コードに変換EXIT_SUCCESS
(または0
)しEXIT_FAILURE
ます。使用するためにはEXIT_SUCCESS
、あなたが持っていたためにそれを渡すためにexit()
、あなたからそれを戻すことができませんでしたmain()
。そのコンパイラのより新しいバージョンがその動作を維持していたかどうかはわかりません。
以前は次のように見える移植可能なCプログラム:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, World!\n");
exit(EXIT_SUCCESS); /* to get good return value to OS */
/*NOTREACHED*/ /* to silence lint warning */
return 0; /* to silence compiler warning */
}
余談ですが、私が正しく思い出せば、終了値のVMS規則は奇数/偶数よりも微妙です。実際には、下位3ビットのようなものを使用して、重大度レベルをエンコードします。ただし、一般的に言って、奇妙な重大度レベルは成功またはその他の情報を示し、偶数のものはエラーを示しました。
returned
ことにより、main
異なったに渡された値からexit
の戻り値の型ならば」が、標準では、具体的言う- main
機能と互換性タイプであるint
、の最初の呼び出しからの戻りmain
関数でありますexit
関数から返された値をmain
引数として関数を呼び出すのと同じです。」それがC11です。C89 / C90の表現はほぼ同じでした。
EXIT_SUCCESS
があるため、値が0のプラットフォーム固有の障害ステータスを返す方法はありませんでした。このため、時代の一部のコンパイラはreturn-from-mainを扱いました。そしてexit()
違う。
実際には違いがあるexit(0)
とreturn(0)
でmain
、あなた- main
関数が複数回呼び出されるが。
次のプログラム
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
return(0);
printf("%d", main(argc - 1, argv));
}
として実行
./program 0 0 0 0
次の出力になります:
00000
しかしこれは:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
exit(0);
printf("%d", main(argc - 1, argv));
}
引数に関係なく何も出力しません。
だれもmain
明示的にあなたを呼び出さないことが確実である場合、それは一般的に技術的に大きな違いではありませんが、より明確なコードを維持exit
することははるかに良く見えます。何らかの理由で電話をかけたいmain
場合は、ニーズに合わせて調整してください。
Cについて話す