web-dev-qa-db-ja.com

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

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

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

143
fredoverflow

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_SUCCESSEXIT_FAILUREで定義された2つのマクロ<cstdlib>は、_main()から返され、それぞれ成功と失敗を示すことができます。

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

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

184
James McNellis

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

戻り値の型はintですが、そうでない場合はその型は実装定義です。すべての実装は、mainの以下の定義の両方を許可します。

int main() { / ... / }およびint main(int argc, char* argv[]) { / ... / }

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

お役に立てば幸いです。

15
liaK

最新の公開された標準(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)
4
M.M

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

3
stonemetal

戻り値とその意味の詳細

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の場合、実装で定義されたステータスの失敗した終了の形式が返されます。それ以外の場合、返されるステータスは実装定義です。

2
Ben Voigt