C++のmain
関数の適切なシグネチャは何ですか?正しい戻り値の型は何ですか?main
から値を返すとはどういう意味ですか?許可されるパラメーターの種類とその意味は何ですか?
これはシステム固有ですか?これらのルールは時間とともに変更されましたか?それらに違反するとどうなりますか?
main
関数は、グローバル名前空間で非メンバー関数として宣言する必要があります。つまり、クラスの静的または非静的メンバー関数にすることも、名前空間(名前のない名前空間であっても)に配置することもできません。
名前main
は、グローバル名前空間の関数として以外はC++で予約されていません。クラス、変数、列挙、メンバー関数、グローバル名前空間にない非メンバー関数など、main
という名前の他のエンティティを自由に宣言できます。
main
という名前の関数をメンバー関数または名前空間で宣言できますが、そのような関数はプログラムの開始位置を指定するmain
関数ではありません。
main
関数は、static
またはinline
として宣言できません。オーバーロードすることもできません。グローバル名前空間に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()
は、成功を示すためにゼロを返し、失敗を示すためにゼロ以外を返すことが期待されています。 main()
にreturn
ステートメントを明示的に記述する必要はありません。明示的にreturn
ステートメントなしでmain()
を返す場合、return 0;
を記述した場合と同じです。次の2つのmain()
関数の動作は同じです。
int main() { }
int main() { return 0; }
EXIT_SUCCESS
とEXIT_FAILURE
で定義された2つのマクロ<cstdlib>
は、_main()
から返され、それぞれ成功と失敗を示すことができます。
main()
によって返される値は、プログラムを終了するexit()
関数に渡されます。
このすべては、ホスト環境(非公式には、完全な標準ライブラリがあり、プログラムを実行するOSがある環境)向けにコンパイルする場合にのみ適用されることに注意してください。独立した環境(たとえば、一部のタイプの組み込みシステム)向けにC++プログラムをコンパイルすることもできます。この場合、起動と終了は完全に実装定義であり、main()
関数は必要ない場合もあります。ただし、最新のデスクトップOS用にC++を作成している場合は、ホスト環境用にコンパイルしています。
標準ドキュメントから、3.6.1.2メイン関数、
戻り値の型はintですが、そうでない場合はその型は実装定義です。すべての実装は、mainの以下の定義の両方を許可します。
int main() { / ... / }
およびint main(int argc, char* argv[]) { / ... / }
後者の形式では、
argc
は、プログラムが実行される環境からのプログラムに渡される引数の数になります。argcがゼロ以外の場合これらの引数はヌル終了マルチバイト文字列の初期文字へのポインタとしてのargv [0]からargv [argc-1] .....
お役に立てば幸いです。
最新の公開された標準(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)
2つの有効なメインはint main()
とint main(int, char*[])
です。他のものはコンパイルされる場合とされない場合があります。 main
が明示的に値を返さない場合、が暗黙的に返されます。
戻り値とその意味の詳細
3.6.1あたり([basic.start.main]
):
main
内のreturnステートメントには、main
関数(自動ストレージ期間を持つオブジェクトを破棄する)を終了し、戻り値を引数としてstd::exit
を呼び出す効果があります。main
ステートメントに出会うことなくreturn
の最後に制御が到達した場合、その効果は実行の効果ですreturn 0;
std::exit
の動作はセクション18.5([support.start.term]
)で詳しく説明されており、ステータスコードについて説明しています。
最後に、制御がホスト環境に戻ります。ステータスがゼロまたは
EXIT_SUCCESS
の場合、ステータスが正常に終了した実装定義の形式が返されます。ステータスがEXIT_FAILURE
の場合、実装で定義されたステータスの失敗した終了の形式が返されます。それ以外の場合、返されるステータスは実装定義です。