C 言語をコンパイルすると、「.OBJ」バイナリ ファイルが生成されます。 C言語のソースプログラムがC言語コンパイラでコンパイルされると、接尾辞「.OBJ」が付いたバイナリファイルが生成され、最終的にこの「.OBJ」ファイルと、C言語コンパイラが提供する各種プログラムを「リンカ」と呼ばれるソフトウェアで結合します。 C 言語。ライブラリ関数が結合されて拡張子「.EXE」が付いたファイルが生成されます。
C言語ソースプログラムがC言語コンパイラによってコンパイルされると、拡張子「.OBJ」が付いたバイナリファイル(オブジェクトファイルと呼ばれます)が生成されます。そして最後に、この「.OBJ」ファイルとC言語が提供する各種ライブラリ関数を「Link」と呼ばれるソフトウェアで接続し、拡張子「.EXE」の付いた実行ファイルを生成します。当然のことですが、C言語はすぐには実行できません。
チュートリアルの推奨: "c 言語チュートリアル ビデオ "
C言語ファイルのコンパイルと実行の 4 つの段階についてそれぞれ説明します
#C 言語のコンパイルとリンクのプロセスでは、作成した c プログラム (ソース コード) を変換する必要があります。ハードウェア上で実行できるプログラム (実行可能コード) をコンパイルしてリンクする必要があります。コンパイルは、テキスト形式のソース コードを機械語形式のオブジェクト ファイルに変換するプロセスです。リンクとは、ターゲット ファイル、オペレーティング システムの起動コード、および使用されるライブラリ ファイルを整理して、最終的に実行可能コードを生成するプロセスです。プロセス図は次のとおりです。
#include ディレクティブは、ヘッダー ファイルの内容を .cpp ファイルに追加する前処理ディレクティブです。コンパイル前にソース ファイルを変更するこの方法では、さまざまなコンピューターやオペレーティング システム環境の制約に適応するための優れた柔軟性が得られます。使用可能なハードウェアまたはオペレーティング システムが異なるため、ある環境に必要なコードは別の環境に必要なコードと異なる場合があります。多くの場合、異なる環境用のコードを同じファイルに配置し、前処理フェーズでコードを変更して現在の環境に適合させることができます。 主に次の側面を扱います:
(
1) #define a b などのマクロ定義命令
この種のディレクティブの場合、プリコンパイルで行う必要があるのは、プログラム内のすべての a を b に置き換えることですが、文字列定数としての a は置き換えられません。 。 #undef もあります。これは、特定のマクロの定義をキャンセルし、今後出現する文字列が置換されないようにするものです。
(2) #ifdef、#ifndef、#else などの条件付きコンパイル命令、#elif、#endif など。
これらの疑似命令の導入により、プログラマはさまざまなマクロを定義することで、コンパイラでどのコードを処理するかを決定できるようになります。プリコンパイラーは、関連ファイルに基づいて不要なコードをフィルターで除外します。
(3) ヘッダー ファイルには、#include 'FileName' や #include # などの命令が含まれています。 ## 待って。
ヘッダー ファイルでは、疑似命令#define は通常、多数のマクロ (最も一般的なものは文字定数) を定義するために使用され、宣言も含まれています。さまざまな外部シンボルの。ヘッダー ファイルを使用する主な目的は、特定の定義を複数の異なる C ソース プログラムで利用できるようにすることです。これらの定義を使用する必要がある C ソース プログラムでは、#include ステートメントを追加するだけでよく、このファイル内でこれらの定義を繰り返す必要はありません。プリコンパイラーは、ヘッダー ファイル内のすべての定義を、コンパイラーによる処理のために生成する出力ファイルに追加します。 c ソース プログラムに含まれるヘッダ ファイルはシステムによって提供されることがあり、通常、これらのヘッダ ファイルは /usr/include ディレクトリに配置されます。プログラム #include では山括弧 (< >) を使用します。さらに、開発者は独自のヘッダ ファイルを定義することもできます。これらのファイルは通常、c ソース プログラムと同じディレクトリに配置されます。この場合は二重引用符 (' ')。 (4
) 特殊記号。プリコンパイラーはいくつかの特殊記号を認識できます。たとえば、ソースプログラム中に現れる LINE
マークは現在の行番号 (10 進数) として解釈され、FILE は現在の行番号 (10 進数) として解釈されます。コンパイル済み Cソース プログラムの名前。プリコンパイラは、ソース プログラム内のこれらの文字列の出現を適切な値に置き換えます。
プリコンパイラが行うことは、基本的にはソース プログラムを「置き換える」ことです。この置換の後、マクロ定義、条件付きコンパイル命令、特殊シンボルを含まない出力ファイルが生成されます。このファイルの意味はプリプロセス前のソースファイルと同じですが、内容が異なります。次に、この出力ファイルはコンパイラの出力として機械語命令に変換されます。
コンパイルと最適化の第 2 段階では、プリコンパイル後に取得される出力ファイルには、数値、文字列、変数定義、main などの C 言語キーワードなどの定数のみが含まれます。 ,if,else,for,while,{ , }、 、-、*、\など。
コンパイラの仕事は、字句解析と構文解析を使用して、すべての命令が文法規則に準拠していることを確認し、それらを同等の中間コード表現またはアセンブリ コードに変換することです。
最適化処理はコンパイルシステムの中でも比較的難しい技術です。これに伴う問題は、コンパイル テクノロジ自体に関連するだけでなく、マシンのハードウェア環境にも大きく関係します。最適化の一環として、中間コードの最適化が行われます。この最適化は特定のコンピューターには依存しません。別の種類の最適化は、主にターゲット コードの生成を目的としています。
前者の最適化では、パブリック式の削除、ループの最適化(コード抽出、強度の弱化、ループ制御条件の変更、既知量のマージなど)、コピー伝播、無駄な代入の削除が主な作業となります。 、など。
後者のタイプの最適化はマシンのハードウェア構造と密接に関係しており、考慮すべき最も重要なことは、マシンの各ハードウェア レジスタに格納されている関連変数の値をどのように活用するかということです。メモリアクセスの回数を減らすためです。さらに、マシン ハードウェア実行命令 (パイプライン、RISC、CISC、VLIW、など)ターゲットコードを短くすることで実行効率が比較的高く、重要な研究テーマでもあります。
アセンブリ
アセンブリとは、実際には、アセンブリ言語コードをターゲットの機械命令に変換するプロセスを指します。翻訳システムによって処理される各 C 言語ソース プログラムに対して、対応するターゲット ファイルがこの処理を通じて最終的に取得されます。ターゲットファイルに格納されるのは、ソースプログラムに相当するターゲットの機械語コードです。オブジェクト ファイルはセグメントで構成されます。通常、オブジェクト ファイルには少なくとも 2 つのセクションがあります。
コード セクション: このセクションには主にプログラム命令が含まれます。このセグメントは通常、読み取りおよび実行可能ですが、通常は書き込み可能ではありません。
データセグメント:主にプログラム内で使用される各種グローバル変数や静的データを格納します。一般に、データ セグメントは読み取り、書き込み、実行が可能です。
UNIX環境には主に 3 つのタイプのターゲット ファイルがあります:
(1)再配置可能ファイル
これには次のものが含まれます。他のオブジェクト ファイルとリンクして実行可能ファイルまたは共有オブジェクト ファイルを作成するのに適したコードとデータがあります。
(2)共有オブジェクト ファイル
このファイルには、両方のコンテキストでのリンクに適したコードとデータが格納されます。 1 つ目は、リンカが他のリロケータブル ファイルや共有オブジェクト ファイルを使用して処理して別のオブジェクト ファイルを作成できること、2 つ目は、ダイナミック リンカが別の実行可能ファイルや他の共有オブジェクト ファイルを使用してそれを処理できることです。画像。
(3)実行ファイル
オペレーティングシステムが作成したプロセスで実行できるファイルが含まれています。アセンブラが実際に生成するのは、最初のタイプのオブジェクト ファイルです。後者の 2 つは、それらを取得するために他の処理が必要であり、これはリンカの仕事です。
リンク処理
アセンブラで生成されたオブジェクトファイルはすぐには実行できず、未解決の問題が多く存在する可能性があります。
たとえば、ソース ファイル内の関数が別のソース ファイルで定義されたシンボル (変数や関数呼び出しなど) を参照する場合や、ライブラリ ファイル内の関数がプログラム内で呼び出される場合があります。 、等。これらの問題はすべてリンカによって解決する必要があります。
リンカの主な仕事は、関連するターゲット ファイルを相互に接続することです。つまり、あるファイルで参照されているシンボルを別のファイルのシンボルの定義に接続して、これらすべてのターゲット ファイルがオペレーティング システムによってロードおよび実行できる統合された全体。
開発者が指定した同じライブラリ関数のリンク方法の違いに基づいて、リンク処理は
(1)スタティックリンク# の 2 種類に分けられます。
# # このリンク モードでは、関数のコードは、関数が配置されている静的リンク ライブラリから最終的な実行可能プログラムにコピーされます。このようにして、プログラムの実行時に、これらのコードがプロセスの仮想アドレス空間にロードされます。静的リンク ライブラリは実際にはオブジェクト ファイルのコレクションであり、各ファイルにはライブラリ内の 1 つまたは関連する関数のグループのコードが含まれています。 (2) ダイナミックリンク
この方法では、関数のコードはいわゆるダイナミックリンクライブラリまたは共有に配置されます。ターゲットファイル内のオブジェクト。このときリンカは、共有オブジェクトの名前とその他の少量の登録情報を最終的な実行可能プログラムに記録します。この実行可能ファイルが実行されると、ダイナミック リンク ライブラリの内容全体が、実行時に対応するプロセスの仮想アドレス空間にマップされます。ダイナミック リンカは、実行可能プログラムに記録されている情報に基づいて、対応する関数コードを見つけます。 実行可能ファイル内の関数呼び出しには、動的リンクまたは静的リンクを使用できます。動的リンクを使用すると、最終的な実行可能ファイルが短くなり、共有オブジェクトが複数のプロセスで使用される場合にメモリを節約できます。これは、この共有オブジェクトのコードのコピーを 1 つだけメモリに保存する必要があるためです。ただし、動的リンクの使用が静的リンクの使用よりも優れていることを必ずしも意味するわけではありません。場合によっては、動的リンクがパフォーマンスに悪影響を与える可能性があります。linux
で使用するgcc コンパイラは、ユーザーが 1 つのコマンドだけでコンパイル作業を完了できるように、上記のプロセスをバンドルしています。しかし、初心者にとってコンパイル プロセスを理解するのは非常に不利です。次の図は、gcc エージェントのコンパイル プロセスです。 上の図からわかるように: プリコンパイル .c ファイルを .i ファイルに変換します 使用される gcc コマンドは次のとおりです: gcc –E 前処理コマンド cpp コンパイルに対応します。 .c/.h ファイルを .s ファイルに変換します 使用する gcc コマンド gcc -S コンパイルコマンド cc -S アセンブリ .s ## を変換します。 # ファイルを .oFile 使用する gcc コマンドは次のとおりです: gcc –c as .o ファイルを実行可能プログラムに変換します gcc コマンド gcc ld Liaこれら 4 つのプロセスで行われる作業を理解することは、ヘッダー ファイルやライブラリなどの作業プロセスを理解するのに役立ちます。また、コンパイルとリンクのプロセスを明確に理解することは、エラーが発生した場合にエラーを見つけるのにも役立ちます。また、プログラミング時にコンパイラのエラー検出を活用することは、非常に役立ちます。
以上がC言語でコンパイルするとどのようなファイルが生成されますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。