CおよびC++でmain()
関数を定義する正しい(最も効率的な)方法は何ですか - int main()
またはvoid main()
- そしてその理由は何ですか? int main()
ならreturn 1
それともreturn 0
?
この質問には次のような多数の重複があります。
main()
関数に有効なシグネチャは何ですか?main()
関数の戻り型void main()
とint main()
の違いは?main()
のシグネチャmain()
の正しい宣言は何ですか? - C++では、非常に良い答えがあります。main()
関数のスタイル /main()
メソッドの戻り値の型 /int main()
vs void main()
関連する
main
の戻り値は、プログラムが終了した方法を示しているはずです。通常の終了は、一般にmain
からの戻り値0で表されます。異常終了は通常、ゼロ以外のリターンによって通知されますが、ゼロ以外のコードがどのように解釈されるかについての標準はありません。また他の人が指摘したように、void main()
はC++標準によって明示的に禁止されているので使用しないでください。有効なC++のmain
シグネチャは次のとおりです。
int main()
そして
int main(int argc, char* argv[])
これはと同等です
int main(int argc, char** argv)
また、C++では、int main()
をreturn-statementなしで残すことができ、その時点ではデフォルトで0が返されます。これはC99プログラムにも当てはまります。 return 0;
を省略するかどうかは議論の余地があります。有効なCプログラムの主なシグネチャの範囲はもっと広いです。
また、効率性はmain
関数の問題ではありません。 C++標準によれば、これは1回しか入れられない(プログラムの開始と終了を示す)。 Cでは、大文字と小文字は区別され、main()
の再入力は許可されていますが、避けるべきです。
受け入れられた答えはC++を対象としているように見えるので、私はCに関連する答えを追加したいと思いました、そしてこれはいくつかの点で異なります。
ISO/IEC 9899:1989(C90):
main()
は次のいずれかとして宣言する必要があります。
int main(void)
int main(int argc, char **argv)
または同等です。たとえば、int main(int argc, char *argv[])
は2番目のものと同じです。さらに、int
戻り型はデフォルトなので省略することができます。
実装がそれを許すなら、main()
は他の方法で宣言されることができます、しかしこれはプログラム実装を定義させ、もはや厳密には適合させません。
標準では、厳密に一致する(つまり、実装定義の動作に依存しない)戻り値を3つ定義しています。成功した場合は0
およびEXIT_SUCCESS
、失敗した場合はEXIT_FAILURE
です。その他の値はすべて非標準であり、実装定義です。未定義の動作を避けるために、main()
の最後には明示的なreturn
ステートメントが必要です。
最後に、プログラムからmain()
を呼び出すことによる標準の観点からは問題はありません。
ISO/IEC 9899:1999(C99):
C99の場合、すべてが上記と同じです。
int
戻り型は省略できません。main()
からreturn文を省略することができます。あなたがそうし、そしてmain()
が終わったら、暗黙のreturn 0
があります。ホスト環境(通常の環境)の場合、C11標準(ISO/IEC 9899:2011)は次のように述べています。
5.1.2.2.1プログラムの起動
プログラムの起動時に呼び出される関数は、
main
という名前です。実装は、この関数のプロトタイプを宣言しません。int
の戻り値の型で、パラメーターなしで定義されます。int main(void) { /* ... */ }
または2つのパラメーター(ここでは
argc
およびargv
と呼ばれますが、宣言されている関数に対してローカルであるため、任意の名前を使用できます):int main(int argc, char *argv[]) { /* ... */ }
または同等;10) または、他の実装定義の方法で。
宣言されている場合、メイン関数のパラメーターは次の制約に従います。
argc
の値は非負でなければなりません。argv[argc]
はNULLポインターでなければなりません。argc
の値がゼロより大きい場合、配列メンバーargv[0]
〜argv[argc-1]
には、プログラム起動前にホスト環境によって実装定義の値が与えられた文字列へのポインタが含まれます。 。その目的は、ホストされた環境の他の場所からプログラムを起動する前に決定された情報をプログラムに提供することです。ホスト環境が大文字と小文字の両方で文字を含む文字列を提供できない場合、実装は文字列が小文字で受信されることを保証しなければなりません。argc
の値がゼロより大きい場合、argv[0]
が指す文字列はプログラム名を表します。プログラム名がホスト環境から利用できない場合、argv[0][0]
はヌル文字でなければなりません。argc
の値が1より大きい場合、argv[1]
からargv[argc-1]
が指す文字列はプログラムパラメーターを表します。- パラメータ
argc
およびargv
およびargv
配列が指す文字列は、プログラムによって変更可能であり、プログラムの起動と終了の間で最後に保存された値を保持します。10) したがって、
int
はint
として定義されたtypedef名で置き換えることができ、またはargv
のタイプはchar **argv
として記述できます。
main()
から返された値は、実装定義の方法で「環境」に送信されます。
5.1.2.2.3プログラムの終了
1
main
関数の戻り値の型がint
と互換性のある型である場合、main
関数の最初の呼び出しからの戻り値は、exit
関数の呼び出しと同じです。引数としてmain
関数によって返される値。11)main
関数を終了する}
に到達すると、値0が返されます。戻り型がint
と互換性がない場合、ホスト環境に返される終了ステータスは指定されていません。11) 6.2.4に従って、自動ストレージ期間が
main
で宣言されたオブジェクトのライフタイムは、前者の場合は終了しますが、後者にはありません。
0
は「成功」として必須であることに注意してください。 EXIT_FAILURE
からEXIT_SUCCESS
および<stdlib.h>
を使用することもできますが、0は十分に確立されており、1も同様です。 255を超える終了コード—可能ですか? 。
C89(およびMicrosoft C)では、main()
関数が戻るが戻り値を指定しない場合に何が起こるかについてのステートメントはありません。したがって、未定義の動作につながります。
7.22.4.4
exit
関数¶5最後に、制御がホスト環境に返されます。
status
の値がゼロまたはEXIT_SUCCESS
の場合、ステータスの成功した終了の実装定義形式が返されます。status
の値がEXIT_FAILURE
の場合、実装定義の形式のステータス不成功終了が返されます。それ以外の場合、返されるステータスは実装定義です。
C++ 11標準(ISO/IEC 14882:2011)は次のように述べています:
3.6.1メイン関数[basic.start.main]
¶1プログラムには、プログラムの指定された開始であるmainというグローバル関数が含まれます。 [...]
¶2実装はメイン関数を事前定義してはなりません。この機能はオーバーロードされません。戻り値の型はint型ですが、それ以外の場合、その型は実装定義です。すべての実装は、mainの次の定義の両方を許可するものとします。
int main() { /* ... */ }
そして
int main(int argc, char* argv[]) { /* ... */ }
後者の形式では、
argc
は、プログラムが実行される環境からプログラムに渡される引数の数です。argc
がゼロ以外の場合、これらの引数はargv[0]
からargv[argc-1]
で、ヌル終了マルチバイト文字列(NTMBS)(17.5.2.1.4.2)およびargv[0]
は、プログラムまたは""
の呼び出しに使用される名前を表すNTMBSの最初の文字へのポインターです。argc
の値は非負でなければなりません。argv[argc]
の値は0になります。[注:argv
の後に追加の(オプションの)パラメーターを追加することをお勧めします。 —注を終了]¶3関数
main
はプログラム内で使用されません。main
のリンケージ(3.5)は実装定義です。 [...]¶5mainのreturnステートメントは、main関数を終了し(自動ストレージ期間を持つオブジェクトを破棄する)、戻り値を引数として
std::exit
を呼び出す効果があります。 returnステートメントに出会うことなく制御がmainの最後に到達した場合、効果は実行return 0;
C++標準は、「[メイン関数]戻り値の型はint
でなければならないが、そうでなければその型は実装定義である」と明示的に述べ、オプションとしてサポートされるC標準と同じ2つの署名を必要とします。したがって、「void main()」はC++標準では直接許可されていませんが、代替を許可する非標準の実装を停止することはできません。 C++は、ユーザーがmain
を呼び出すことを禁止していることに注意してください(C標準では禁止されています)。
C++ 11標準には§18.5開始と終了の段落があり、§7.22.4.4の段落と同じですThe exit
function脚注(EXIT_SUCCESS
およびEXIT_FAILURE
が<cstdlib>
で定義されていることを単に文書化する)を除き、C11標準(上記で引用)。
従来、Unixシステムは3番目のバリアントをサポートしています。
int main(int argc, char **argv, char **envp) { ... }
3番目の引数は、文字列へのポインターのヌル終了リストです。各ポインターは、名前、等号、および値(空の場合もある)を持つ環境変数です。これを使用しない場合でも、 'extern char **environ;
'を使用して環境にアクセスできます。長い間、それはそれを宣言したヘッダーを持っていませんでしたが、 POSIX 2008標準では<unistd.h>
で宣言する必要があります。
これは、付録Cに文書化されている共通の拡張機能としてC標準で認識されています。
J.5.1環境引数
¶1ホスト環境では、メイン関数は3番目の引数
char *envp[]
を受け取ります。これはchar
へのポインターのnullで終わる配列を指し、それぞれはについての情報を提供する文字列を指しますプログラムのこの実行のための環境(5.1.2.2.1)。
Microsoft VS 201 コンパイラは興味深いものです。ウェブサイトは言う:
Mainの宣言構文は
int main();
または、オプションで、
int main(int argc, char *argv[], char *envp[]);
または、
main
およびwmain
関数は、void
(戻り値なし)を返すように宣言できます。main
またはwmain
をvoidを返すと宣言した場合、returnステートメントを使用して、親プロセスまたはオペレーティングシステムに終了コードを返すことはできません。main
またはwmain
がvoid
として宣言されているときに終了コードを返すには、exit
関数を使用する必要があります。
void main()
を含むプログラムが終了するときに何が起こるか(親またはOSにどの終了コードが返されるか)が明確ではありません。MSWebサイトもサイレントです。
興味深いことに、MSは、CおよびC++標準が必要とするmain()
の2引数バージョンを規定していません。 3番目の引数がchar **envp
(環境変数のリストへのポインター)である3つの引数形式のみを規定します。
Microsoftのページには、他のいくつかの選択肢もリストされています。wmain()
は、ワイド文字列などを取ります。
Microsoft Visual Studio 2005 バージョンの このページ は、代替としてvoid main()
をリストしません。 バージョン Microsoftから Visual Studio 2008 以降。
前述のとおり、上記の要件はホスト環境に適用されます。自立型の環境(ホストされた環境の代替)で作業している場合、標準には言うべきことがほとんどありません。独立した環境では、プログラムの起動時に呼び出される関数はmain
と呼ばれる必要はなく、戻り値の型に制約はありません。標準は言う:
5.1.2実行環境
自立型とホスト型の2つの実行環境が定義されています。どちらの場合も、指定されたC関数が実行環境によって呼び出されると、プログラムの起動が発生します。静的ストレージ期間を持つすべてのオブジェクトは、プログラムの起動前に初期化(初期値に設定)する必要があります。それ以外の場合、このような初期化の方法とタイミングは指定されていません。プログラムの終了は、実行環境に制御を返します。
5.1.2.1独立した環境
独立した環境(Cプログラムの実行はオペレーティングシステムの利点なしで行われる可能性がある)では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。独立したプログラムで利用できるライブラリ機能は、4節で必要とされる最小限のセット以外は、実装定義です。
自立型環境でのプログラム終了の効果は実装定義です。
4適合への相互参照はこれを参照します:
¶5厳密に適合するプログラムは、この国際規格で指定された言語とライブラリの機能のみを使用するものとします。3) 不特定、未定義、または実装定義の動作に依存する出力を生成してはならず、最小実装制限を超えてはなりません。
¶6適合実装の2つの形式は、hostedとfreestandingです。 準拠のホストされた実装は、厳密に準拠したプログラムを受け入れます。 準拠の自立型実装は、ライブラリ節(第7節)で指定された機能の使用が標準ヘッダー
<float.h>
、<iso646.h>
、<limits.h>
、<stdalign.h>
、<stdarg.h>
、<stdbool.h>
、<stddef.h>
、<stdint.h>
、および<stdnoreturn.h>
。準拠する実装には、厳密に準拠するプログラムの動作を変更しない限り、拡張機能(追加のライブラリ関数を含む)があります。4)¶7適合プログラムは、適合実装に受け入れられるものです。5)
3) 厳密に適合するプログラムは、関連するマクロを使用する適切な条件付き包含前処理指令によって使用が保護されている場合、条件付き機能(6.10.8.3を参照)を使用できます。例えば:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */ /* ... */ fesetround(FE_UPWARD); /* ... */ #endif
4) これは、準拠する実装が、この国際標準で明示的に予約されている識別子以外の識別子を予約しないことを意味します。
5) 厳密に準拠するプログラムは、準拠する実装間で最大限に移植できることを目的としています。適合プログラムは、適合実装の移植性のない機能に依存する場合があります。
関数を実際に定義する独立した環境に必要なヘッダーは<stdarg.h>
だけであることに注意してください(そして、それらはマクロである場合があります-そしてしばしばそうです-)。
C標準がホスト環境と自立環境の両方を認識するように、C++標準も認識します。 (ISO/IEC 14882:2011からの引用)
1.4実装コンプライアンス[intro.compliance]
¶72種類の実装が定義されています:ホスト実装と自立実装。ホストされた実装の場合、この国際標準は利用可能なライブラリのセットを定義します。自立型実装とは、オペレーティングシステムの恩恵を受けずに実行できる実装であり、特定の言語サポートライブラリ(17.6.1.3)を含む実装定義のライブラリセットを備えています。
¶8準拠する実装は、整形式プログラムの動作を変更しない限り、拡張機能(追加のライブラリ関数を含む)を持つことができます。この国際規格に従って不正な形式の拡張を使用するプログラムを診断するには、実装が必要です。ただし、そうすれば、そのようなプログラムをコンパイルして実行できます。
¶9各実装には、サポートされない条件付きでサポートされるすべての構成要素を特定し、ロケール固有の特性をすべて定義するドキュメントを含めるものとします。3
3) このドキュメントでは、実装定義の動作も定義しています。 1.9を参照してください。
17.6.1.3自立型実装[コンプライアンス]
ホスト型と自立型(1.4)の2種類の実装が定義されています。ホストされた実装の場合、この国際規格は利用可能なヘッダーのセットを記述します。
独立した実装には、実装定義のヘッダーセットがあります。このセットには、少なくとも表16に示すヘッダーが含まれます。
提供されるヘッダーのバージョン
<cstdlib>
は、少なくとも関数abort
、atexit
、at_quick_exit
、exit
、およびquick_exit
(18.5)を宣言するものとします。 。この表にリストされている他のヘッダーは、ホストされた実装と同じ要件を満たします。表16 —独立した実装のためのC++ヘッダー
Subclause Header(s) <ciso646> 18.2 Types <cstddef> 18.3 Implementation properties <cfloat> <limits> <climits> 18.4 Integer types <cstdint> 18.5 Start and termination <cstdlib> 18.6 Dynamic memory management <new> 18.7 Type identification <typeinfo> 18.8 Exception handling <exception> 18.9 Initializer lists <initializer_list> 18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool> 20.9 Type traits <type_traits> 29 Atomics <atomic>
int main()
を使用するのはどうですか?C11標準の標準§5.1.2.2.1は優先表記法— int main(void)
—を示していますが、標準にはint main()
を示す2つの例もあります。 §6.5.3.4¶8 および §6.7.6.3¶2 。ここで、例は「規範的」ではないことに注意することが重要です。それらは例示にすぎません。例にバグがある場合、それらは標準のメインテキストに直接影響しません。とはいえ、それらは予想される動作を強く示しているため、標準に例にint main()
が含まれている場合、たとえ推奨表記ではなくても、int main()
は禁止されていないことを示唆します。
6.5.3.4
sizeof
および_Alignof
演算子…
¶8例3この例では、可変長配列のサイズが計算され、関数から返されます:
#include <stddef.h> size_t fsize3(int n) { char b[n+3]; // variable length array return sizeof b; // execution time sizeof } int main() { size_t size; size = fsize3(10); // fsize3 returns 13 return 0; }
main()
はEXIT_SUCCESS
かEXIT_FAILURE
のどちらかを返すべきだと思います。それらはstdlib.h
で定義されています
CおよびC++標準では、自立型とホスト型の2種類の実装が定義されていることに注意してください。
C90ホスト環境
許可されたフォーム 1:
int main (void)
int main (int argc, char *argv[])
main (void)
main (int argc, char *argv[])
/*... etc, similar forms with implicit int */
コメント:
前者の2つは許可された形式として明示的に記述されていますが、その他はC90が戻り値の型と関数のパラメーターに「暗黙のint」を許可したため、暗黙的に許可されています。他のフォームは許可されていません。
C90自立環境
Mainの任意の形式または名前が許可されます 2。
C99ホスト環境
許可されたフォーム 3:
int main (void)
int main (int argc, char *argv[])
/* or in some other implementation-defined manner. */
コメント:
C99は「暗黙のint」を削除したため、main()
は無効になりました。
「または他の実装定義の方法で」奇妙で曖昧な文が導入されました。これは、「int main()
のパラメーターは異なる場合がある」または「mainは実装定義の形式を持つことができる」と解釈できます。
一部のコンパイラは、後者の方法で標準を解釈することを選択しました。間違いなく、標準を引用することで厳密に準拠していないと簡単に述べることはできません。
ただし、main()
の完全にワイルドな形式を許可することは、おそらくこの新しい文の意図ではありませんでした(?)。 C99の理論的根拠(規範的ではない)は、文がint main
への追加パラメーターを参照していることを意味します 4。
それでも、ホスト環境プログラムの終了に関するセクションでは、mainがintを返さない場合について議論しています。 5。このセクションはmainの宣言方法の規範ではありませんが、ホストされたシステム上でもmainが完全に実装定義された方法で宣言される可能性があることを明確に暗示しています。
C99自立環境
Mainの任意の形式または名前が許可されます 6。
C11ホスト環境
許可されたフォーム 7:
int main (void)
int main (int argc, char *argv[])
/* or in some other implementation-defined manner. */
C11自立環境
Mainの任意の形式または名前が許可されます 8。
int main()
は、上記のバージョンのいずれのCのホストされた実装の有効なフォームとしてもリストされなかったことに注意してください。 Cでは、C++とは異なり、()
と(void)
の意味は異なります。前者は、言語から削除される可能性のある廃止された機能です。 C11の将来の言語方向を参照してください。
6.11.6関数宣言子
空の括弧を使用した関数宣言子(プロトタイプ形式のパラメーター型宣言子ではない)の使用は、廃止された機能です。
C++ 03ホスト環境
許可されたフォーム 9:
int main ()
int main (int argc, char *argv[])
コメント:
最初のフォームの空の括弧に注意してください。この場合、C++とCは異なります。C++では、これは関数がパラメーターを受け取らないことを意味するためです。しかし、Cでは、任意のパラメーターを使用できることを意味します。
C++ 03自立環境
起動時に呼び出される関数の名前は実装定義です。名前がmain()
の場合、指定された形式に従う必要があります 10:
// implementation-defined name, or
int main ()
int main (int argc, char *argv[])
C++ 11ホスト環境
許可されたフォーム 11:
int main ()
int main (int argc, char *argv[])
コメント:
標準のテキストは変更されましたが、同じ意味があります。
C++ 11自立環境
起動時に呼び出される関数の名前は実装定義です。名前がmain()
の場合、指定された形式に従う必要があります 12:
// implementation-defined name, or
int main ()
int main (int argc, char *argv[])
参照
ANSI X3.159-1989 2.1.2.2ホスト環境。 「プログラムの起動」
プログラムの起動時に呼び出される関数の名前はmainです。実装は、この関数のプロトタイプを宣言しません。戻り値の型intで定義され、パラメーターなしで定義されます。
int main(void) { /* ... */ }
または、2つのパラメーター(ここではargcおよびargvと呼びますが、宣言されている関数に対してローカルであるため、任意の名前を使用できます):
int main(int argc, char *argv[]) { /* ... */ }
ANSI X3.159-1989 2.1.2.1自立環境:
独立した環境(Cプログラムの実行はオペレーティングシステムの利点なしで行われる可能性がある)では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。
ISO 9899:1999 5.1.2.2ホスト環境-> 5.1.2.2.1プログラムの起動
プログラムの起動時に呼び出される関数の名前はmainです。実装は、この関数のプロトタイプを宣言しません。戻り値の型intで定義され、パラメーターなしで定義されます。
int main(void) { /* ... */ }
または、2つのパラメーター(ここではargcおよびargvと呼びますが、宣言されている関数に対してローカルであるため、任意の名前を使用できます):
int main(int argc, char *argv[]) { /* ... */ }
または同等; 9)または他の実装定義の方法で。
国際標準の根拠—プログラミング言語— C、リビジョン5.10。 5.1.2.2ホスト環境-> 5.1.2.2.1プログラムの起動
Mainの引数の動作、exit、main、およびatexitの相互作用(§7.20.4.2を参照)は、argv文字列の表現とmainによって返される値の意味の望ましくない多様性を抑制するために成文化されました。
Mainの引数としてのargcとargvの仕様は、広範囲にわたる従来の慣行を認識しています。 argv [argc]は、一般的な慣行にもとづいて、リストの最後に冗長チェックを提供するために、nullポインターである必要があります。
mainは、0個または2個の引数で移植可能に宣言できる唯一の関数です。 (他の関数の引数の数は、呼び出しと定義の間で正確に一致する必要があります。)この特殊なケースは、プログラムがプログラムの引数文字列にアクセスしないときにmainに引数を残す広範な慣行を単に認識します多くの実装はmainに対する3つ以上の引数をサポートしていますが、そのような慣行は標準によって祝福も禁止もされていません。 mainを3つの引数で定義するプログラムは厳密には準拠していません(§J.5.1を参照)。
ISO 9899:1999 5.1.2.2ホスト環境-> 5.1.2.2.3プログラムの終了
メイン関数の戻り値の型がintと互換性のある型である場合、メイン関数への最初の呼び出しからの戻り値は、引数としてメイン関数によって返された値を使用してexit関数を呼び出すことと同じです; 11)
}
に到達するメイン関数を終了し、値0を返します。戻り値の型がintと互換性がない場合、ホスト環境に返される終了ステータスは指定されていません。
ISO 9899:1999 5.1.2.1独立した環境
独立した環境(Cプログラムの実行はオペレーティングシステムの利点なしで行われる可能性がある)では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。
ISO 9899:2011 5.1.2.2ホスト環境-> 5.1.2.2.1プログラムの起動
このセクションは、上記で引用したC99と同じです。
ISO 9899:1999 5.1.2.1独立した環境
このセクションは、上記で引用したC99と同じです。
ISO 14882:2003 3.6.1メイン関数
実装では、メイン関数を事前定義してはなりません。この機能はオーバーロードされません。戻り値の型はint型ですが、それ以外の場合、その型は実装定義です。すべての実装は、mainの次の定義の両方を許可するものとします。
int main() { /* ... */ }
そして
int main(int argc, char* argv[]) { /* ... */ }
ISO 14882:2003 3.6.1メイン関数
独立した環境のプログラムがメイン関数を定義するために必要かどうかは、実装で定義されます。
ISO 14882:2011 3.6.1メイン機能
実装では、メイン関数を事前定義してはなりません。この機能はオーバーロードされません。戻り値の型はint型ですが、それ以外の場合、その型は実装定義です。すべての実装は両方を許可するものとします
—()がintを返す関数および
—(int、charへのポインターへの)intを返す関数
メインのタイプとして(8.3.5)。
ISO 14882:2011 3.6.1メイン機能
このセクションは、上記で引用したC++ 03と同じです。
成功した場合は0を、エラーの場合は0以外を返します。これは、あなたのプログラムで何が起こったのかを調べるためにUNIXとDOSのスクリプトによって使用される標準です。
C89およびK&R Cのmain()
の未指定の戻り型はデフォルトで 'int`になります。
return 1? return 0?
int main()
にreturn文を書かないと、終了時の{
はデフォルトで0を返します。
return 0
またはreturn 1
は、親プロセスによって受け取られます。シェルではシェル変数に変換されます。プログラムをシェルから実行していてその変数を使用していない場合は、main()
の戻り値について心配する必要はありません。
どのようにして私のメイン関数が返したものを得ることができますか? を参照してください。
$ ./a.out
$ echo $?
このようにして、main()
の戻り値の最下位バイトを受け取るのは変数$?
であることがわかります。
UnixおよびDOSスクリプトでは、成功した場合はreturn 0
、エラーの場合はゼロ以外の値が通常返されます。これは、あなたのプログラムで何が起こったのかを調べてフロー全体を制御するために、UnixおよびDOSのスクリプトで使用されている標準です。
Intを返す場合でも、一部のOS(Windows)では返される値が1バイト(0-255)に切り捨てられることに注意してください。
オペレーティングシステムは、戻り値を使用してプログラムがどのように閉じられたかを確認できます。
戻り値0は通常、ほとんどのオペレーティングシステム(とにかく考えることができるもの)ではOKを意味します。
自分でプロセスを呼び出したときにも確認でき、プログラムが正常に終了して終了したかどうかを確認できます。
これはNOT単なるプログラミング規約です。
main()
の戻り値は、プログラムがどのように終了したかを示します。戻り値がzero
であれば、それは実行が成功したことを意味し、ゼロ以外の値は何かが実行において悪くなったことを表します。
私は、成功したリターンはOSベースであるため、standardがmainには戻り値を必要としないと規定しているという印象の下にありました。成功した戻り値自体を挿入するためのコンパイラ。
しかし、私は通常0を返します。
0を返すと、プログラムはジョブを正常に終了したことをプログラマーに知らせるはずです。
CおよびC++でmain()関数を定義するための正しい(最も効率的な)方法は何ですか - int main()またはvoid main() - そしてその理由は何ですか?
「(最も効率的な)」という言葉は問題を変えません。あなたが自立した環境にいない限り、main()
を宣言する普遍的に正しい方法が一つあり、それはintを返すことです。
main()
はCとC++で何を返すべきですか?
が main()
を返すべきではなく、 が main()
が返すものです。 main()
は、もちろん、他の誰かが呼び出す関数です。 main()
を呼び出すコードを管理することはできません。そのため、呼び出し元と一致するように、main()
を型が正しい署名で宣言する必要があります。あなたは単に問題について何の選択もありません。その答えはすでにCおよびC +標準によって完全に明確に定義されているので、多かれ少なかれ効率的なもの、より良いまたはより悪いスタイル、あるいはそのようなものを自問する必要はありません。ただ従ってください。
Int main()が1を返すのか、0を返すのか
成功した場合は0、失敗した場合はゼロ以外。繰り返しになりますが、選択する必要はありません。つまり、準拠しているはずのインターフェースによって定義されます。
プロセスから整数を返す効率に関して本当に問題がある場合は、おそらくこのプロセスを何度も呼び出すことは避けてください。この戻り値が問題になります。
これを行っている場合(プロセスを何度も呼び出す)、呼び出しごとに特定のプロセスを割り当てることなく、呼び出し側の内部またはDLLファイルに直接ロジックを配置する方法を見つける必要があります。この場合、複数プロセスの割り当てにより、関連する効率の問題が生じます。
詳細に言えば、0を返す方が1を返すよりも多かれ少なかれ効率的かどうかを知りたいだけならば、それは場合によってはコンパイラに依存する可能性があります。コード、関数の結果などでは、まったく同じ数のクロックサイクルが必要です。
何を返すかは、実行可能ファイルに対して何をしたいのかによって異なります。たとえば、コマンドラインシェルでプログラムを使用している場合は、成功した場合は0を返し、失敗した場合は0以外を返す必要があります。そうすれば、コードの結果に応じて、プログラムを条件付き処理でシェル内で使用できるようになります。また、重大なエラーの場合は、プログラムのさまざまな出口点でさまざまな終了値でプログラムを終了させることができます。呼び出し側のシェルはこれを使用して、返された値を調べて対処できます。コードがシェルでの使用を意図しておらず、戻り値が誰にも気にしないのであれば、それは省略されるかもしれません。私は個人的に署名int main (void) { .. return 0; .. }
を使います
return 0
を省略CまたはC++プログラムがmain
の終わりに達すると、コンパイラは自動的にコードを生成して0を返します。したがって、main
の末尾に明示的にreturn 0;
を置く必要はありません。
注: 私がこの提案をするとき、それはほとんど常に2種類のコメントのうちの1つがそれに続きます: "私はそれを知りませんでした。"または「それは悪いアドバイスです!」私の理論的根拠は、標準で明示的にサポートされているコンパイラの動作に頼ることが安全で有用だということです。 Cの場合、C99以降。 ISO/IEC 9899:1999のセクション5.1.2.2.3を参照してください。
[...]
main
関数への最初の呼び出しからの戻りは、exit
関数によって返された値を引数としてmain
関数を呼び出すことと同じです。main
関数を終了する}
に到達すると、値0が返されます。
C++では、1998年の最初の標準以来。 ISO/IEC 14882:1998のセクション3.6.1を参照してください。
Return文に遭遇せずに制御がmainの終わりに達すると、return 0が実行されます。
それ以降の両方の規格のすべてのバージョン(C99およびC++ 98)は同じ考え方を維持しています。 C++で自動的に生成されたメンバ関数に頼っており、void
関数の最後に明示的なreturn;
ステートメントを書く人はほとんどいません。省略の理由は "それは変に見えます" にまとめられているようです。もし私と同じように、C標準への変更の論理的根拠について知りたければ この質問を読んで 。また、1990年代初頭には、これは未定義の動作(広くサポートされていましたが)であったため、「ずさんなやり方」と見なされていました。
だから私はそれを省略することを提唱します。いずれにせよ、それを省略しているコードに遭遇した場合、それが標準によって明示的にサポートされていることがわかり、それが何を意味するのかがわかります。
これがリターンコードの使い方の簡単なデモンストレーションです...
Linux端末が提供するさまざまなツールを使用するときは、プロセスが完了した後のエラー処理などに戻りコードを使用できます。次のテキストファイルmyfileが存在するとします。
これはgrepがどのように機能するかをチェックするための例です。
Grepコマンドを実行すると、プロセスが作成されます。それが通過したら(そして壊れなかった)それは0から255の間のあるコードを返します。例えば:
$ grep order myfile
もしあなたがそうするなら
$ echo $?
$ 0
あなたは0を取得します。なぜですか? grep が一致を見つけて終了コード0を返したからです。これは成功して終了するための通常の値です。もう一度チェックしてみましょう。ただし、テキストファイル内にないものがあるため、一致するものは見つかりません。
$ grep foo myfile
$ echo $?
$ 1
Grepはトークン "foo"と私たちのファイルの内容を一致させることができなかったので、戻りコードは1です(これは失敗が起こるときの通常のケースですが、上で述べたようにたくさんの値があります)。
非常に基本的ですが、今度は次のbashスクリプト(単純にLinux端末でそれを入力します)がエラー処理のアイデアを与えるはずです。
$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found
2行目以降は、 "foo"がgrepを1に戻してから端末に何も出力されず、grepの戻りコードが0に等しいかどうかがチェックされます。 == 1。
あなたがこれを呼んでいるかどうか、そしてそのプロセスを見てわかるように、それが何を返したのかを見ることが時々不可欠です(main()の戻り値によって)。