void
forの返品タイプmain()
が許可されている場所を知っているのは本の著者だけのようです。C++標準はそれを完全に禁止しています。
C標準では、標準形式は次のとおりです。
int main(void) { ... }
と
int main(int argc, char **argv) { ... }
引数の型に対して代替の同等の形式の宣言を許可します(もちろん、名前は関数のローカル変数であるため、完全に任意です)。
C標準は、「他の実装定義の方法で」小さな規定を設けています。ISO / IEC 9899:2011規格には、次のように記載されています。
5.1.2.2.3プログラムの終了
関数の戻り型がとmain
互換性のある型である場合、関数int
への最初の呼び出しからの戻りは、関数によって返された値を引数として関数main
を呼び出すことと同じです。11) main関数を終了するに到達すると、値0が返されます。戻りタイプがと互換性がない場合、ホスト環境に返される終了ステータスは指定されていません。exit
main
}
int
11) 6.2.4に従い、メインで自動保存期間が宣言されているオブジェクトの存続期間は、後者では終了しない場合でも、前者の場合で終了します。
これにより、int
返品不可が明らかになりますが、指定されていないことが明確になります。したがって、一部の実装でvoid
はの戻り型として許可されている可能性がありmain()
ますが、それはドキュメントからのみ見つけることができます。
(私はC2011標準を引用していますが、基本的に同じ言葉がC99にあり、そのための私のテキストはオフィスにあり、私はそうではありませんが、C89を信じています。)
ちなみに、規格の付録Jには次のように記載されています。
J.5一般的な拡張機能
次の拡張機能は多くのシステムで広く使用されていますが、すべての実装に移植できるわけではありません。厳密に準拠したプログラムが無効になる可能性のある拡張機能を含めると、実装が非準拠になります。このような拡張機能の例としては、新しいキーワード、標準ヘッダーで宣言された追加のライブラリ関数、またはアンダースコアで始まらない名前の事前定義されたマクロがあります。
J.5.1環境引数
ホストされた環境では、main
関数は3番目の引数を受け取ります。これは、プログラムのこの実行のための環境に関する情報を提供する文字列を指すchar *envp[]
、nullで終了するポインタの配列を指します(5.1.2.2.1 char
)。
なぜ機能void main()
するのですか?
質問はそれが機能することを観察しvoid main()
ます。コンパイラがプログラムのコードを生成するために最善を尽くすため、「機能」します。GCCなどのコンパイラは、の非標準形式について警告しmain()
ますが、それらを処理します。リンカはリターンタイプについてあまり心配していません。シンボルが必要なだけでmain
(_main
システムによっては、場合によっては)、シンボルが見つかったら、実行可能ファイルにリンクします。起動コードは、main
が標準的な方法で定義されていることを前提としています。スタートアップコードに戻ると、関数がをmain()
返したかのように戻り値を収集しますint
が、その値はガベージである可能性があります。したがって、プログラムの終了ステータスを検索しない限り、それは一種の機能を果たしているように見えます。