mainの適切な宣言は何ですか?


147

mainC ++ での関数の適切なシグネチャは何ですか?正しい戻り値の型とは何mainですか?から値を返すとはどういう意味ですか?許可されているパラメーターのタイプとは何ですか?それらの意味は何ですか?

これはシステム固有ですか?それらのルールは時間とともに変化しましたか?違反した場合はどうなりますか?


1
これは、CおよびC ++で返されるものmainと非常に密接に関連しているか、その複製です
Jonathan Leffler

@JonathanLeffler冗談ではありません... 約8か月前のリビジョン6の重複のリストに追加されました。
fredoverflow 2014年

回答:


192

mainこの関数はグローバル名前空間内の非メンバ関数として宣言する必要があります。つまり、クラスの静的メンバー関数または非静的メンバー関数にすることも、名前空間(名前のない名前空間であっても)に配置することもできません。

この名前mainは、グローバル名前空間の関数として以外は、C ++では予約されていません。mainクラス、変数、列挙、メンバー関数、グローバル名前空間にない非メンバー関数など、他のエンティティを自由に宣言できます。

mainメンバー関数または名前空間で名前が付けられた関数を宣言できますが、そのような関数はmainプログラムの開始場所を指定する関数ではありません。

mainこの関数はとして宣言することはできませんstaticinline。また、オーバーロードすることもできません。mainグローバル名前空間で指定できる関数は1つだけです。

main機能は、プログラムで使用することはできません:あなたは呼び出すことが許可されていないmain、あなたのコード内のどこからでも機能し、またあなたは、そのアドレスを取ることが許可されています。

の戻り値の型はでmainなければなりませんint。他の戻り値の型は許可されていません(戻り値の型がで宣言されmainている誤ったプログラムがよく見られるため、この規則は太字になっていvoidます。これは、main関数に関して最も頻繁に違反している規則です)。

main許可する必要のある宣言が2つあります。

int main()               // (1)
int main(int, char*[])   // (2)

(1) 、パラメーターはありません。

(2)、2つのパラメータがあり、それらは、従来命名されargcそしてargv、それぞれ、。 argvプログラムへの引数を表すC文字列の配列へのポインタです。配列argc内の引数の数ですargv

通常、argv[0]プログラムの名前が含まれていますが、常にそうであるとは限りません。 argv[argc]nullポインタであることが保証されています。

配列型引数(などchar*[])は実際には変装された単なるポインタ型引数であるため、次の2つはどちらも有効な書き込み方法(2)であり、どちらもまったく同じ意味です。

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

一部の実装では、他のタイプと数のパラメーターを使用できます。実装のドキュメントをチェックして、それが何をサポートしているかを確認する必要があります。

main()成功を示すにはゼロを返し、失敗を示すにはゼロ以外を返すことが期待されています。にreturnステートメントを明示的に記述する必要はありません。明示的なステートメントなしでreturn main()を許可する場合は、記述した場合と同じです。次の2つの関数の動作は同じです。main()returnreturn 0;main()

int main() { }
int main() { return 0; }

そこ二つのマクロがあり、EXIT_SUCCESSかつEXIT_FAILURE、で定義されて<cstdlib>からも返すことができるようmain()、それぞれ、成功と失敗を示します。

によって返された値は関数にmain()渡されexit()、プログラムが終了します。

これはすべて、ホストされた環境(非公式には、完全な標準ライブラリがあり、プログラムを実行しているOSがある環境)でコンパイルする場合にのみ適用されることに注意してください。自立型環境(たとえば、一部のタイプの組み込みシステム)用にC ++プログラムをコンパイルすることもできます。その場合、起動と終了は完全に実装定義であり、main()関数が不要な場合もあります。ただし、最新のデスクトップOS用のC ++を作成している場合は、ホスト環境向けにコンパイルしています。


1
IIRCで保証される戻り値は、0、EXIT_SUCCESS(0と同じ効果)、およびEXIT_FAILUREのみです。編集:ああ、OK、他のゼロ以外のステータス値が返されることがありますが、実装定義の意味があります。EXIT_FAILUREのみが何らかの方法でエラー値として解釈されることが保証されています。
デリックターク

4
@Synetech:最初の文で、「C ++のメイン関数の適切なシグネチャは何ですか?」という質問です。質問には[c ++]と[c ++-faq]の両方のタグが付いています。JavaまたはC#ユーザー(または他のユーザー)がまだ混乱している場合、私はそれを手伝うことはできません。C#にはMain、非メンバー関数さえないため、静的メンバー関数である必要があります。C89でさえmain戻る必要がありintます。私はその正確なルールを知っているK&R Cと十分に精通していないが、私はそれも必要と推測main返すようにintするのでmainノーリターン型が暗黙的=やや一般的で無いタイプではなかったとintK&Rインチ
James McNellis、2010

3
@Suhail:言語標準では戻り値の型はになるはずintですから。
James McNellis、2011年

1
@Suhail:はい。あなたのコードは正しいC ++ではなく、多くのコンパイラはあなたのコードを拒否します。
James McNellis、2011年

2
@Suhail:Visual C ++では、void戻り値の型を言語拡張として許可しています。これを許可しないコンパイラには、GCCとコモーが含まれます。
James McNellis、2011年

15

標準ドキュメントから、3.6.1.2メイン関数

戻り型はint型ですが、それ以外の場合はその型は実装定義です。すべての実装は、以下のメインの定義の両方を許可するものとします。

int main() { / ... / } そして int main(int argc, char* argv[]) { / ... / }

後者の形式でargc、プログラムが実行される環境からプログラムに渡される引数数になります。argcがゼロ以外の場合、これらの引数は、初期値へのポインターとしてargv [0]からargv [argc-1]で提供されます。 nullで終了するマルチバイト文字列の文字 .....

お役に立てれば幸いです。


2
の戻り値の型がmainどうあるべきかについて特定の理由はありますintか?
Suhail Gupta

1
@SuhailGupta:呼び出しプロセスがこのプロセスが成功したと見なすべきかどうかを知るため。voidそのモデルを壊すことができます。「常に成功と見なす」という意味だったとしても、意味がありません。プロセスが実際に失敗したかどうかを言う方法がなかったので、本当に成功しましたか?いいえ、戻りintます。
オービットの軽さのレース2017年

4

最新の公開標準(C ++ 14)の正確な表現は次のとおりです。

実装は両方を許可するものとします

  • ()戻る機能int

  • 関数、戻り(intへのポインターへのポインターchar)int

のタイプとしてmain

これは、代替スペルがそのように長いの種類として許可されていることを明らかにmainタイプですint()int(int, char**)。したがって、以下も許可されます。

  • int main(void)
  • auto main() -> int
  • int main ( )
  • signed int main()
  • typedef char **a; typedef int b, e; e main(b d, a c)

1
NB。私はこの回答を別のスレッドへのコメントとして投稿しました。誰かがこのスレッドをint main(void)C ++では正しくない証拠として引用しようとしました。
2017

3
@Stargateurにauto main() -> intは、推定戻り型がありません。「(auto main(){...は許可されていません)」の{に注意してください。意味のあるものを追加するのに十分な知識がまだない場合は、そのことを知ってください。

3

2つの有効な電源があるint main()int main(int, char*[])。それ以外のものはコンパイルされる場合とされない場合があります。場合はmain、明示的に値を返さない、0が暗黙的に返されます。


1
戻り値の型mainが無効であると言及したときに、コードがコンパイルされないのを見たことはありません。mainの戻り型がintである必要がある特定の理由はありますか?
Suhail Gupta

4
言語仕様によると、mainには戻り型のintが必要です。コンパイラで許可されているその他の戻り値の型は、コンパイラ固有の拡張機能です。基本的にvoidを使用するということは、C ++に似ているがC ++ではない言語でプログラミングしていることを意味します。
11

2
標準がintの戻り値の型としてを必要とする理由mainは、この値がプログラムの終了コードとしてシェルに渡され、をsh期待するためintです。
uckelman 2013

たぶんその理由はしつけですか?複数のパスが存在する可能性があります。戻り値の型voidがすべて無音の場合。ではint、からの戻りごとに特定の終了値を定義する必要がありますmain
Andreas Spindler 2018年

2

戻り値とその意味の詳細

3.6.1に従って([basic.start.main]):

のreturnステートメントはmainmain関数を終了し(自動ストレージ期間を持つオブジェクトを破棄)std::exit、引数として戻り値を使用して呼び出します。制御がステートメントにmain出会わずに最後に到達した場合return、結果は実行の結果です

return 0;

の動作はstd::exitセクション18.5([support.start.term])で詳しく説明されており、ステータスコードについて説明しています。

最後に、制御がホスト環境に戻ります。ステータスがゼロまたはの場合EXIT_SUCCESS、ステータスが正常に終了したという実装定義のフォームが返されます。statusがのEXIT_FAILURE場合、実装が定義した形式のステータスが正常に終了しなかったことが返されます。それ以外の場合、返されるステータスは実装定義です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.