h ファイルは、.c (.cpp) ファイルの先頭に配置されることが多いため、「ヘッダー ファイル」と呼ばれます。 h ファイルは、.c ファイルから繰り返し宣言ステートメントを抽出し、それを新しいファイルに配置し、必要な .c (.cpp) ファイルに「#include XXXX」のようなステートメントを入力するファイルです。
このチュートリアルの動作環境: Windows7 システム、C 17 バージョン、Dell G3 コンピューター。
コンパイラが.c(.cpp))ファイルしか認識せず、何が何だか分からなかった時代当時、人々は多くの .c (.cpp) ファイルを作成していましたが、徐々に、多くの .c (.cpp) ファイルの宣言ステートメントは同じであるが、単語ごとに繰り返す必要があることがわかりました。これらの内容を各 .c (.cpp) ファイルに入力します。しかし、さらに恐ろしいのは、宣言の 1 つが変更されると、すべての .c (.cpp) ファイルをチェックする必要があることです。
そのため、繰り返しの部分を抽出して新しいファイルに配置し、必要な .c (.cpp) ファイルに #include XXXX のようなステートメントを入力します。このようにして、特定のステートメントが変更された場合でも、どこでも検索して変更する必要はありません。この新しいファイルは .c (.cpp) ファイルの先頭に配置されることが多いため、「ヘッダー ファイル」という名前が付けられ、拡張子は .h です。
言語学習の初期段階では、プログラムには .c ファイルが 1 つまたはいくつかしか含まれていないことがよくありますが、現時点では、ヘッダー ファイルの構成に悩まされることはほとんどありません。 、コード量は数千行、場合によっては数万行に達し、ファイル数も増加しています。このとき、これらのファイルの構成が問題となるのですが、実はこれらのファイルの構成は、理論的にはソフトウェア工学などにおけるモジュール設計の問題となります。
ヘッダー ファイルの役割の簡単な説明:
(1) ヘッダー ファイルを通じてライブラリ関数を呼び出します。多くの場合、ヘッダー ファイルとバイナリ ライブラリがユーザーに提供されている限り、ソース コードをユーザーに公開するのは不便です (または許可されません)。ユーザーは、ヘッダー ファイル内のインターフェイス宣言に従ってライブラリ関数を呼び出すだけでよく、インターフェイスがどのように実装されているかを気にする必要はありません。コンパイラは、対応するコードをライブラリから抽出します。
(2) ヘッダー ファイルはタイプ セーフティ チェックを強化できます。ヘッダー ファイルの宣言と矛盾する方法でインターフェイスが実装または使用されている場合、コンパイラはエラーを指摘します。この単純なルールにより、プログラマのデバッグとエラー修正の負担が大幅に軽減されます。
たとえば、aaa.h で関数宣言を定義し、aaa.h と同じディレクトリに aaa.c を作成します。この関数の実装は aaa.c で定義され、その後 # main 関数が配置されている .c ファイルにこの aaa.h を含めると、この関数を使用できるようになります。 main が実行されると、この関数を定義する aaa.c ファイルが見つかります。これは、main 関数が標準 C/C のプログラム エントリ ポイントであり、コンパイラが最初に関数が配置されているファイルを検索するためです。
コンパイラーが myproj.c (main() を含む) をコンパイルするときに、mylib.h (関数 void test() を宣言する) が含まれていることを検出すると、コンパイラーはプリセット設定に従います。パス (インクルード パス リストとコード ファイルが配置されているパス) は、同じ名前 (拡張子 .cpp または .c、この場合は mylib.c) の実装ファイルを探します (ファイルが見つかった場合)。関数がその中に見つかった場合 (この例では void test())、コンパイルを続行します。
指定されたディレクトリに実装ファイルが見つからない場合、またはそのファイルと後続のインクルード ファイルに実装コードが見つからない場合は、コンパイル エラーが返されます。実際には、インクルード プロセスが「見える」ことがあります。ファイル結合処理では、宣言と実装をそれぞれヘッダファイルとCファイルに記述するか、両方を同時にヘッダファイルに記述するかですが、理論的には本質的な違いはありません。
理論的には、C ファイルとヘッダー ファイルの内容が C 言語でサポートされていれば、何でも記述できます。たとえば、ヘッダー ファイルに関数本体を記述する場合、 C ファイルには次のものが含まれます。 このヘッダー ファイルは、この関数をターゲット ファイルの一部にコンパイルできます (コンパイルは C ファイルに基づいて行われます。このヘッダー ファイルが C ファイルに含まれていない場合、このコードは役に立ちません)。C で実行できます。 file 関数宣言、変数宣言、構造体宣言、これは問題ありません。 ! !では、なぜヘッダー ファイルと C ファイルに分割する必要があるのでしょうか?また、関数、変数宣言、マクロ宣言、構造体宣言は通常ヘッダーで行われるのはなぜでしょうか? C ファイルで変数を定義する場合、関数の実装はどうなるでしょうか? ?
C ファイルとヘッダファイルの違いを理解するには、まずコンパイラの動作プロセスを理解する必要がありますが、一般的にコンパイラは次のような処理を行います。ステージ
2. 字句解析および構文解析ステージ
3. コンパイル段階では、最初に純粋なアセンブリ文にコンパイルし、次にそれらをCPU関連のバイナリコードにアセンブルして各ターゲットファイルを生成します
4. 接続フェーズでは、各ターゲット ファイル内の各コード セグメントの絶対アドレスが配置され、特定のプラットフォームに関連する実行可能ファイルが生成されます。コンパイラは C ファイル単位でコンパイルします。プロジェクト内に C ファイルが 1 つも存在しない場合、プロジェクトはコンパイルされません。コネクタはターゲット ファイルに基づいています。1 つ以上のターゲット ファイル内の関数と変数を再配置して、最終的な実行可能ファイルを生成します。PC でのプログラム開発の場合、一般に main 関数があり、これは各コンパイラの規則です。最終的な実行可能ファイルを生成するには、いくつかのターゲット ファイル、つまり C ファイルが必要であり、これらの C ファイルには実行可能プログラムのエントリ ポイントとして main 関数が必要です。
C言語のコンパイルは、簡単に言うと前処理、コンパイル、アセンブル、リンク(test.c test.h =>test.i =>test.s =>test)に分かれます。 .o = > test) 4 つの主要な段階。 c ファイルの #include マクロ処理は、前処理段階で c で参照されている h ファイルの内容をすべて c ファイルに書き込み、最終的に .i 中間ファイルを生成します。このとき、h ファイルの内容は次のようになります。 c ファイルに書き込まれるのと同等です。
これは、コードを再利用するためのチャネルも提供します。多くの c ファイルが同じ h ファイルを参照できるため、h ファイルは複数の c ファイルに配置され、複数回コンパイルされます。これは、定義ができない理由でもあります。 h ファイルに置くことはできますが、宣言だけなので、定義を置くと複数回コンパイルされます プログラムをリンクした場合(複数の int a、システム内で強いシンボル定義が定義されている場合)、エラーになります 宣言が異なります. 宣言 定義の拡張が最終的には一つの定義になることを意味するため、リンク時に重複定義のエラーが発生しません。
プログラミングでは、h ファイルでこの形式を使用したことがあるはずです
#ifndef XXX_H #define XXX_H //…… #endif
はは、何に使うのですか? h ファイルが相互に参照するときに重複した定義を排除します。もちろん、マクロ定義は前処理段階で役割を果たし、コンパイル後のプロセスではマクロの影はありません。
A.h int a(); B.h #include "A.h" C.h #include "A.h" D.h #include "A.h" #include "B.h"
上記の D.h ファイルでは int a(); のステートメントが 2 つ繰り返されており、少し繰り返しになりますが、このとき条件付きコンパイル マクロが役立ちます
A.h #ifndef A_H #define A_H int a(); #endif
これそうすれば定義の重複はなくなります。
推奨チュートリアル: "C#"
以上がhファイルとcファイルの関係は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。