c では、メイン関数はどこで定義されていますか?コンパイラまたはヘッダー ファイルで定義されていますか?コンパイラは「メイン」ワードの意味をどのように認識しますか? 私はどこにも答えを得ることができませんでした、助けてください。
7 に答える
一般に、オペレーティングシステムはエントリポイント(Unixでは一般的にstart
関数)を定義します。このエントリポイントは、オペレーティングシステム(特にローダー)によって自動的に呼び出されます。Cコンパイラには、最小限のランタイムセットアップ(ここでも、Unixではほとんどの場合呼び出されますcrt0.o
)が付属しています。これは、プリコンパイルされたオブジェクトファイルであり、Cライブラリの内部をセットアップしてからmain()関数を呼び出します。したがって、コンパイラはそれとは何の関係もありません。それはcrt0.oとその仕事をするオペレーティングシステムです。
どちらにも定義されていません。main
実際にはCのキーワードではなく、単なる通常の関数です。
標準Cライブラリには、初期環境を設定し(収集argc
などargv
)、関数を呼び出すmain
関数が含まれています。
次に、リンカはその関数の場所をエントリポイントとしてオブジェクトファイルに配置します。
glibc
ここでのエントリポイント
を確認できます:http: //fossies.org/dox/glibc-2.15/dl-init_8c_source.html
関数の意味はmain
、言語仕様の一部です。
コンパイラには、それを処理するための特別なコードがあります。
cで定義されている主な関数は、コンパイラまたはヘッダーファイルで定義されています。
(免責事項:ウィンドウの色付きの説明)
この関数main
はC標準の一部であり、通常はプログラムの開始点であり、特別なヘッダーは必要ありません。「main」という名前は、オペレーティングシステムにとって実際には重要ではありません。代わりに、リンカはデフォルトでプログラムの開始点としてmainを設定しますが、名前は実際にはプログラム内の他の関数である可能性があります。
リンカには、プログラム内の別のエントリポイントを指定するオプションがあります。これは、プログラムの実行を開始する開始点にすぎませんが、オペレーティングシステムの観点からは、main、_tmain、WinMainのいずれと呼ばれるかは関係ありません。
コパイラーがアプリケーションを生成する場合、コードには2つの主要な部分があります。
- OSグルーコード
- プログラマーによって作成されたアプリケーション(メインを含む)
実行時に生成されたアプリケーションは、OSグルーコードを実行し、関数mainを呼び出します。したがって、コンパイラがアプリケーションのコードを生成しているときに、関数mainが見つからない場合、コンパイルに失敗します。それが見つかった場合、それはそのアドレスを知っているので、それを呼び出す方法を知っています。
mainについて本当に特別なことは何もありません(コンパイラがそれを探すことを除いて)。
C では、独立型とホスト型の 2 種類の実行環境を使用できます。5.1.2/1 を参照:
独立型とホスト型の 2 つの実行環境が定義されています。どちらの場合も、指定された C 関数が実行環境によって呼び出されると、プログラムの起動が発生します。
でも:
そのような初期化の方法とタイミングは、それ以外の場合は指定されていません。プログラムが終了すると、制御が実行環境に戻ります。
5.1.2.1/1 による独立した環境 (組み込みシステムを考えてください):
独立した環境 (オペレーティング システムの恩恵を受けずに C プログラムの実行が行われる環境) では、プログラムの起動時に呼び出される関数の名前と型は実装定義です。
ほとんどの(デスクトップ)一般的なシステムは、ホストされたカテゴリに属します。つまり、プログラムを実行するためのコンテキストを提供するホストまたは OS があるカテゴリです。そのような環境では (5.1.2.2.1/1 を参照):
プログラムの起動時に呼び出される関数は main と呼ばれます。
main
キーワードではありません (つまり、6.4.1 で定義されたセットにありません)。これは、ホスト (OS) を備えたシステムから C プログラムを実行および実行するための拘束力のある契約と考えてください。したがって、ブートストラップ コードがこの特定の関数を検索できるようにすることはベンダーの責任であり、適切な定義を提供することはプログラマの責任です。
Call stack
コンピュータ プログラムのアクティブなサブルーチンの情報を格納します。Main() 関数は既にコンパイラによって定義されているため、コール スタックと同様のデータ構造に格納する必要があります。このリンク
http://en.wikipedia を参照してください。 org/wiki/Call_stack
これがお役に立てば幸いです。