main()
の2つの有効なバージョンがC++
に存在します。
int main() // version 1
int main(int argc, char **argv) // version 2
ただし、両方の過負荷を同時に共存させることはできません。何故なの? (潜在的な使用例:端末からプログラムを実行しているときに、引数が渡されない場合は最初のバージョンが呼び出され、それ以外の場合は2番目のバージョンが呼び出されます。)
コンパイラは、バイナリごとに1つのバージョンのみを許可する特別なチェックを実行しますか?
§3.6.1/ 2(C++ 03)は言う
実装は、
main
関数を事前定義してはなりません。 この関数はオーバーロードされません。戻り値の型はint型でなければなりませんが、それ以外の場合、その型は実装定義です。すべての実装では、次のmainの定義の両方を許可する必要があります。
int main() { /* ... */ }
int main(int argc, char* argv[]) { /* ... */ }
どちらでも使用できます。どちらも標準に準拠しています。
また、char *argv[]
はchar **argv
と同等であるため、char *argv[]
をchar **argv
に置き換えても違いはありません。
ただし、両方のバージョンを同時に共存させることはできません。 (ユースケースは次のようになります:コマンドプロンプトからバイナリを実行しているときに、引数を渡さない場合は、最初のバージョンを呼び出す必要があります。それ以外の場合は、2番目のバージョンを呼び出す必要があります)。
いいえ。両方のバージョンを同時に共存させることはできません。 1つのプログラムに1つのmain
関数を含めることができます。どちらを選択するかによって異なります。コマンドライン引数を処理する場合は、2番目のバージョンを選択する必要があります。そうでない場合は、最初のバージョンで十分です。また、2番目のバージョンを使用し、コマンドライン引数を渡さない場合は、害がないことにも注意してください。エラーは発生しません。それに応じてargc
とargv
を解釈する必要があり、それらの値に基づいて、プログラムのロジックとフローを作成する必要があります。
WindowsとUnixには次のものがあります。
int main(int argc, char **argv, char **envp)
およびWin32アプリには次のものがあります。
int WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
macOSには次のものがあります。
int main(int argc, char **argv, char **envp, char **Apple)
main
は通常、プログラムの実行時にOSが最初に呼び出すものではないことを忘れないでください。 main
関数は、ランタイム環境によって呼び出される関数です。実行する最初の命令のアドレスは、通常、一部のメタデータで宣言されます。通常、実行可能ファイルの場合は開始時に宣言されます。
上記のいずれも、私が知る限り、C/C++標準と矛盾するものはありません。ただし、1つしかない場合は、OSが複数ある場合にどちらを呼び出すかわからないため、これは理にかなっています。 1つしかないことの確認は、コンパイラでは行われず、リンカで行われます。
セクション3.6.1.2 C++ Standard 1998および2003エディションの両方の状態:
実装は、主な機能を事前に定義してはなりません。 この関数はオーバーロードされません。戻り値の型はint型でなければなりませんが、それ以外の場合、その型は実装定義です。
さらに、
ISO C++標準(ISO/IEC 14882:1998)は、特にmainがintを返すことを要求しています。これには、整形式のプログラムに対する明示的な「shall」制約があります。
セクション§3.6.1¶2:
戻り値の型はintですが、それ以外の場合、その型は実装定義です。すべての実装では、次のmainの定義の両方を許可する必要があります。
int main() { /* … */ }
そして
int main(int argc, char* argv[]) { /* … */ }
したがって、main
の両方のバージョンが標準で許可されており、どちらを使用するかはプログラマーの実装設定として残されています。
メインはC時代に定義されました。これは、printfのルールに沿って設定されています。 main
を可変個引数関数と見なします。
int main(...)
標準では、引数なしと2つのポインタ引数で問題ないとされています。ただし、実装がより多くの引数を提供したい場合、実装は自由にそうすることができます。
2つのmain
sを持つことができない理由は、Cプログラムでprintf
のような関数を2回定義できないのと同じ理由です。確かに、printf
は異なる引数をサポートし、そこにある引数に応じて動作を変更しますが、C++という用語の意味で過負荷ではありません。
標準では、main
はオーバーロードできないとされています。マングルされておらず、同じアンマングル名で2つの関数を持つことはできません。これによりリンクエラーが発生すると思いますが、コンパイラーは、より明確なエラーメッセージを表示するために、明示的なチェックを追加することができます。
int main(int argc, char **argv)
とint main()
を優先署名にする必要がありますが、コンパイラーはさまざまなパラメーターを使用してmain
を自由に受け入れることができます。
C++でmain()をオーバーロードすることはできません。コンパイラは次のエラーを示しました。
error C2731: 'main' : function cannot be overloaded