795

main()C および C++ で関数を定義する正しい (最も効率的な) 方法は何ですか?int main()またvoid main()、その理由は何ですか? そして、議論はどうですか?もしそうならint main()return 1またはreturn 0


この質問には、次のような多数の重複があります。

関連している:

4

18 に答える 18

643

の戻り値mainは、プログラムがどのように終了したかを示します。通常の終了は、 からの戻り値 0 によって表されますmain。異常終了はゼロ以外のリターンによって通知されますが、ゼロ以外のコードがどのように解釈されるかについての標準はありません。他の人が指摘したようにvoid main()、C++ 標準で禁止されているため、使用しないでください。有効な C++main署名は次のとおりです。

int main()

int main(int argc, char* argv[])

これはと同等です

int main(int argc, char** argv)

int main()また、C++ では、 return ステートメントなしで残すことができ、その時点でデフォルトで 0 を返すことにも注意してください。これは、C99 プログラムにも当てはまります。return 0;省略すべきかどうかは議論の余地があります。有効な C プログラムの主な署名の範囲は、はるかに大きくなっています。

効率はmain関数の問題ではありません。C++ 標準に従って、(プログラムの開始と終了をマークする) 1 回だけ入力および終了できます。C の場合、再入力main()は許可されますが、避ける必要があります。

于 2008-10-15T12:16:08.277 に答える
204

受け入れられた回答はC ++を対象としているように見えるので、Cに関連する回答を追加すると思いましたが、これはいくつかの点で異なります. また、ISO/IEC 9899:1989 (C90) と ISO/IEC 9899:1999 (C99) の間にいくつかの変更が加えられました。

main()次のいずれかとして宣言する必要があります。

int main(void)
int main(int argc, char **argv)

または同等。たとえば、int main(int argc, char *argv[])は 2 番目のものと同等です。C90ではint戻り値の型がデフォルトなので省略できますが、C99以降ではint戻り値の型を省略できません。

実装で許可されている場合main()は、他の方法 (例: ) で宣言できますがint main(int argc, char *argv[], char *envp[])、これによりプログラムの実装が定義され、厳密に準拠しなくなります。

標準では、厳密に準拠している (つまり、実装で定義された動作に依存しない) 戻り値として、成功した終了と0失敗した終了の 3 つの値が定義されています。その他の値は非標準であり、実装によって定義されます。C90 では、未定義の動作を避けるために、最後に明示的なステートメントが必要です。C99 以降では、return ステートメントを から省略できます。実行して終了すると、暗黙的な.EXIT_SUCCESSEXIT_FAILUREmain()returnmain()main()return 0

最後に、標準の観点からは、C プログラムからmain() 再帰的に呼び出すことには何の問題もありません。

于 2008-10-16T09:59:57.177 に答える
65

または のいずれかmain()を返す必要があると思います。それらはで定義されていますEXIT_SUCCESSEXIT_FAILUREstdlib.h

于 2008-10-15T12:33:14.733 に答える
43

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 では戻り値の型と関数パラメーターに "implicit int" が許可されているため、他の形式は暗黙的に許可されています。他の形式は許可されていません。

  • C90 自立型環境

main の任意の形式または名前が許可されます2

  • C99 ホスト環境

許可されたフォーム3 :

int main (void)
int main (int argc, char *argv[])
/* or in some other implementation-defined manner. */

コメント:

C99 は「implicit int」を削除したためmain()、有効ではなくなりました。

「または他の実装定義の方法で」という奇妙で曖昧な文が導入されました。int main()これは、「パラメーターが異なる場合がある」または「メインは実装定義の任意の形式を持つことができる」と解釈できます。

一部のコンパイラは、後者の方法で標準を解釈することを選択しました。おそらく、標準自体があいまいであるため、標準自体を引用することによって、それらが準拠していないと簡単に述べることはできません。

しかし、完全に乱暴な形を許すことmain()はおそらく(?)、この新しい文の意図ではありません。int main C99 の理論的根拠 (規範的ではない) は、文が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[])

参考文献

  1. ANSI X3.159-1989 2.1.2.2 ホスト環境。「プログラム起動」

プログラムの起動時に呼び出される関数は main と呼ばれます。実装は、この関数のプロトタイプを宣言していません。これは、戻り値の型が int で、パラメーターなしで定義されます。

int main(void) { /* ... */ } 

または 2 つのパラメーター (ここでは argc および argv と呼ばれますが、宣言されている関数に対してローカルであるため、任意の名前を使用できます):

int main(int argc, char *argv[]) { /* ... */ }
  1. ANSI X3.159-1989 2.1.2.1 自立型環境:

独立した環境 (オペレーティング システムの恩恵を受けずに C プログラムの実行が行われる環境) では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。

  1. 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) または他の実装定義の方法で。

  1. 国際標準 — プログラミング言語 — 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 は、ゼロまたは 2 つの引数で移植可能に宣言できる唯一の関数です。(他の関数の引数の数は、呼び出しと定義の間で正確に一致する必要があります。) この特殊なケースは、プログラムがプログラムの引数文字列にアクセスしない場合に main の引数を省略するという広範な慣行を単に認識しています。多くの実装では main に対して 2 つ以上の引数がサポートされていますが、そのような慣行は標準によって祝福も禁止もされていません。main を 3 つの引数で定義するプログラムは厳密には準拠していません (§J.5.1 を参照)。

  1. ISO 9899:1999 5.1.2.2 ホスト環境 --> 5.1.2.2.3 プログラムの終了

main 関数の戻り値の型が int と互換性のある型である場合、main 関数の最初の呼び出しからの戻りは、main 関数によって返された値を引数として exit 関数を呼び出すことと同等です。11)}終了する に到達するmain 関数は値 0 を返します。戻り値の型が int と互換性がない場合、ホスト環境に返される終了ステータスは規定されていません。

  1. ISO 9899:1999 5.1.2.1 自立型環境

独立した環境 (オペレーティング システムの恩恵を受けずに C プログラムの実行が行われる環境) では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。

  1. ISO 9899:2011 5.1.2.2 ホスト環境 -> 5.1.2.2.1 プログラムの起動

このセクションは、上記の C99 セクションと同じです。

  1. ISO 9899:1999 5.1.2.1 自立型環境

このセクションは、上記の C99 セクションと同じです。

  1. ISO 14882:2003 3.6.1 主な機能

実装は、メイン関数を事前定義してはなりません。この関数はオーバーロードされません。型 int の戻り値の型を持つ必要がありますが、それ以外の場合、その型は実装定義です。すべての実装は、main の次の定義の両方を許可する必要があります。

int main() { /* ... */ }

int main(int argc, char* argv[]) { /* ... */ }
  1. ISO 14882:2003 3.6.1 主な機能

独立した環境のプログラムがメイン関数を定義する必要があるかどうかは、実装によって定義されます。

  1. ISO 14882:2011 3.6.1 主な機能

実装は、メイン関数を事前定義してはなりません。この関数はオーバーロードされません。型 int の戻り値の型を持つ必要がありますが、それ以外の場合、その型は実装定義です。すべての実装では、両方を許可する必要があります

— int を返す () の関数と

— int を返す (int、char へのポインターへのポインター) の関数

メインのタイプとして (8.3.5)。

  1. ISO 14882:2011 3.6.1 主な機能

このセクションは、上記の C++03 セクションと同じです。

于 2015-07-07T08:07:30.277 に答える
30

成功した場合は 0 を返し、エラーの場合は 0 以外を返します。これは、UNIX および DOS スクリプトで、プログラムで何が起こったのかを調べるために使用される標準です。

于 2008-10-15T12:16:51.503 に答える
8

main()C89 および K&R C では、指定されていない戻り値の型はデフォルトで 'int' になります。

return 1? return 0?
  1. で return ステートメントを記述しない場合int main()、終了}はデフォルトで 0 を返します。

(c++ および c99 以降のみ。c90 の場合は return ステートメントを記述する必要があります。なぜ main がここで 0 を返さないのですか?を参照してください。 )

  1. return 0またはreturn 1、親プロセスによって受信されます。シェルでは、シェル変数に入ります。プログラムをシェルから実行していて、その変数を使用していない場合は、 の戻り値について心配する必要はありませんmain()

メイン関数が返したものを取得するにはどうすればよいですか? を参照してください。.

$ ./a.out
$ echo $?

$?このようにして、 の戻り値の最下位バイトを受け取るのは変数であることがわかりますmain()

Unix および DOS スクリプトでreturn 0は、通常、成功すると非ゼロが返され、エラーの場合は 0 以外が返されます。これは、Unix および DOS スクリプトで使用される標準であり、プログラムで何が起こったのかを調べ、フロー全体を制御します。

于 2011-12-27T08:02:51.533 に答える
7

int を返している場合でも、一部の OS (Windows) では戻り値が 1 バイト (0 ~ 255) に切り捨てられることに注意してください。

于 2008-10-15T15:22:13.313 に答える
4

オペレーティング システムは戻り値を使用して、プログラムがどのように閉じられたかを確認できます。

戻り値 0 は通常、ほとんどのオペレーティング システム (私が思いつくもの) で OK を意味します。

また、自分でプロセスを呼び出したときにもチェックでき、プログラムが正常に終了して終了したかどうかを確認できます。

これは単なるプログラミング規約ではありません。

于 2011-07-01T16:32:34.087 に答える
3

の戻り値はmain()、プログラムがどのように終了したかを示します。戻り値がzeroである場合は、実行が成功したことを意味しますが、ゼロ以外の値は、実行中に何か問題が発生したことを表します。

于 2011-07-01T23:30:59.867 に答える
2

0 を返すことで、プログラムがジョブを正常に終了したことをプログラマーに伝える必要があります。

于 2012-11-23T07:29:29.500 に答える
1

プロセスから整数を返す効率に本当に問題がある場合は、そのプロセスを何度も呼び出して、この戻り値が問題になることを避ける必要があります。

これを行う (プロセスを何度も呼び出す) 場合は、呼び出しごとに特定のプロセスを割り当てずに、ロジックを呼び出し元の内部または DLL ファイルに直接配置する方法を見つける必要があります。この場合、複数のプロセス割り当てにより、関連する効率の問題が発生します。

詳細には、0 を返すことが 1 を返すよりも多かれ少なかれ効率的かどうかだけを知りたい場合は、場合によってはコンパイラに依存する可能性がありますが、一般的に、同じソース (ローカル、フィールド、定数、埋め込み) から読み取られると仮定します。コード、関数の結果など) には、まったく同じ数のクロック サイクルが必要です。

于 2011-03-03T11:56:57.407 に答える
1

何を返すかは、実行可能ファイルで何をしたいかによって異なります。たとえば、コマンド ライン シェルでプログラムを使用している場合、成功の場合は 0 を返し、失敗の場合はゼロ以外を返す必要があります。その後、コードの結果に応じて条件付き処理を行うシェルでプログラムを使用できます。また、解釈に従ってゼロ以外の値を割り当てることもできます。たとえば、重大なエラーの場合、さまざまなプログラムの終了点が異なる終了値でプログラムを終了する可能性があり、返された値を調べることで何をすべきかを決定できる呼び出し側シェルで利用できます。コードがシェルでの使用を意図しておらず、戻り値が誰にも迷惑をかけない場合は、省略される可能性があります。私は個人的に署名を使用しますint main (void) { .. return 0; .. }

于 2011-03-10T14:11:33.747 に答える
1

これは、リターン コードの使用法の小さなデモです...

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

「foo」がgrepを1に戻し、grepの戻りコードが0に等しいかどうかを確認するため、2行目以降は端末に何も出力されません.2番目の条件ステートメントは、CHECKにより真であるため、最後の行にメッセージをエコーし​​ます== 1。

このプロセスとそのプロセスを呼び出しているかどうかがわかるように、(main() の戻り値によって) 返されたものを確認することが不可欠な場合があります。

于 2015-02-10T22:22:08.667 に答える