C および C++ 標準では、独立型とホスト型の 2 種類の実装が定義されていることに注意してください。
許可されたフォーム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" が許可されているため、他の形式は暗黙的に許可されています。他の形式は許可されていません。
main の任意の形式または名前が許可されます2。
許可されたフォーム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 が完全に実装定義の方法で宣言される可能性があることを明確に示しています。
main の任意の形式または名前を使用できます6。
許可されたフォーム7 :
int main (void)
int main (int argc, char *argv[])
/* or in some other implementation-defined manner. */
main の任意の形式または名前を使用できます8。
int main()
は、上記のバージョンのいずれにおいても、C のホストされた実装の有効な形式としてリストされていないことに注意してください。C では、C++()
と(void)
は異なり、意味が異なります。前者は、言語から削除される可能性がある古い機能です。C11 の将来の言語の方向性を参照してください。
6.11.6 関数宣言子
括弧が空の関数宣言子 (プロトタイプ形式のパラメーター型宣言子ではない) の使用は廃止予定の機能です。
許可されたフォーム9 :
int main ()
int main (int argc, char *argv[])
コメント:
最初の形式の空の括弧に注意してください。この場合、C++ と C は異なります。これは、C++ では関数がパラメーターをとらないことを意味するためです。ただし、C では、任意のパラメーターを使用できることを意味します。
起動時に呼び出される関数の名前は実装定義です。名前が付けられている場合は、指定されmain()
た形式に従う必要があります10 :
// implementation-defined name, or
int main ()
int main (int argc, char *argv[])
許可されたフォーム11 :
int main ()
int main (int argc, char *argv[])
コメント:
規格のテキストは変更されていますが、意味は同じです。
起動時に呼び出される関数の名前は実装定義です。名前を付ける場合は、指定されmain()
た形式に従う必要があります12 :
// implementation-defined name, or
int main ()
int main (int argc, char *argv[])
参考文献
- ANSI X3.159-1989 2.1.2.2 ホスト環境。「プログラム起動」
プログラムの起動時に呼び出される関数は main と呼ばれます。実装は、この関数のプロトタイプを宣言していません。これは、戻り値の型が int で、パラメーターなしで定義されます。
int main(void) { /* ... */ }
または 2 つのパラメーター (ここでは argc および argv と呼ばれますが、宣言されている関数に対してローカルであるため、任意の名前を使用できます):
int main(int argc, char *argv[]) { /* ... */ }
- ANSI X3.159-1989 2.1.2.1 自立型環境:
独立した環境 (オペレーティング システムの恩恵を受けずに C プログラムの実行が行われる環境) では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。
- 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) または他の実装定義の方法で。
- 国際標準 — プログラミング言語 — 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 を参照)。
- ISO 9899:1999 5.1.2.2 ホスト環境 --> 5.1.2.2.3 プログラムの終了
main 関数の戻り値の型が int と互換性のある型である場合、main 関数の最初の呼び出しからの戻りは、main 関数によって返された値を引数として exit 関数を呼び出すことと同等です。11)}
終了する に到達するmain 関数は値 0 を返します。戻り値の型が int と互換性がない場合、ホスト環境に返される終了ステータスは規定されていません。
- ISO 9899:1999 5.1.2.1 自立型環境
独立した環境 (オペレーティング システムの恩恵を受けずに C プログラムの実行が行われる環境) では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。
- ISO 9899:2011 5.1.2.2 ホスト環境 -> 5.1.2.2.1 プログラムの起動
このセクションは、上記の C99 セクションと同じです。
- ISO 9899:1999 5.1.2.1 自立型環境
このセクションは、上記の C99 セクションと同じです。
- ISO 14882:2003 3.6.1 主な機能
実装は、メイン関数を事前定義してはなりません。この関数はオーバーロードされません。型 int の戻り値の型を持つ必要がありますが、それ以外の場合、その型は実装定義です。すべての実装は、main の次の定義の両方を許可する必要があります。
int main() { /* ... */ }
と
int main(int argc, char* argv[]) { /* ... */ }
- ISO 14882:2003 3.6.1 主な機能
独立した環境のプログラムがメイン関数を定義する必要があるかどうかは、実装によって定義されます。
- ISO 14882:2011 3.6.1 主な機能
実装は、メイン関数を事前定義してはなりません。この関数はオーバーロードされません。型 int の戻り値の型を持つ必要がありますが、それ以外の場合、その型は実装定義です。すべての実装では、両方を許可する必要があります
— int を返す () の関数と
— int を返す (int、char へのポインターへのポインター) の関数
メインのタイプとして (8.3.5)。
- ISO 14882:2011 3.6.1 主な機能
このセクションは、上記の C++03 セクションと同じです。