2009-06-06 18 views
4

ライブラリのソースコードを読むと、同じ名前のファイルが.c.hであることがわかります。主な情報源には.hファイルが含まれていますが、.cファイルは含まれていません。 .hファイルのコードを見ると、同じ名前のファイルも#includeではありません。何か不足していますか?同じ名前の.hファイルが#include 'dの場合、コンパイラは自動的に.cファイルをインクルードしますか?どのように同じ名前の.cと.hファイルをリンクしますか?

答えて

6

いいえ.cファイルを.hファイルに含める必要はありません。通常、.hファイルはコンパイラー入力として直接渡されませんが、その唯一の目的は他のファイルに含まれることです。

通常、それはのようなものです:あなたが "a.c" と "b.c" をコンパイルし、出力ファイルをリンク

"a.c" includes "a.h" 
"b.c" includes "c.h" 

4

.hファイルには、.cファイル内の関数の宣言が含まれています。これらの宣言は、別の.cファイルの機能を使用する他の.cファイルで必要となります。したがって、.cファイルは.hファイルには含まれません。

各.cファイルはオブジェクトファイルにコンパイルされ、これらのオブジェクトファイルはすべてライブラリまたはアプリケーションにリンクされます。

8

典型的なファイル.hは、関数プロトタイプやtypedefなどを含む.cファイルの「目次」として機能します。プログラムには.hが含まれているので、機能やタイプについて知ることができます。

.cファイルは別々にコンパイルされ、実際のコードを含むオブジェクトファイル(.oまたは.obj)を生成します。

オブジェクトファイルは、メイクファイル、プロジェクトファイルなどの方法でメインプログラムに結び付けられます。その後、オブジェクトファイルはメインプログラムにリンクされ、機能的な全体が生成されます。

ライブラリの場合、メインプログラムなしです。オブジェクトファイルは一緒に集められ、特殊なフォーマット(静的または動的ライブラリ用)に置かれます。ライブラリを使用するプログラムは、上記のように.hを含み、ライブラリに対してリンクします。

1

プリプロセッサは魔法を何もしません。

インクルードディレクトリ内に何かを含めるには(ハード、独自のヘッダを行うには)

#include <foo.h> 

または同じコンパイルディレクトリ内の何かを含むように

#include "foo.h" 

それがテキストを取るんすべてfoo.hを直接出力に接続してください。 gcc a.c -Eは、前処理後の外観を表示します。

#includeを正しく処理する独自のプログラムを作成することは、簡単なことです。

7

魔法はありません。 Cプログラムがコンパイルされると、2つの大きなステップがあります。

まず、個々のコンパイル単位が個別にコンパイルされます。 (コンパイル単位は、基本的に1つの.cファイルとそれに含まれるすべてのファイルです)。

この段階では、他の.cファイルに含まれる内容については何も知らないため、完全なプログラムを生成することはできません。それができることは、いくつかの "空白を埋める"スポットを持つコードを生成することです。 foo.cからbar.hで宣言され、bar.cで定義された関数を呼び出すと、コンパイラはその関数が存在することのみを知ることができます。これはbar.hで宣言されているので、完全な定義があると仮定する必要がありますsomewhere。しかし、その定義は別のコンパイル単位の中にあるため、まだ見ることはできません。したがってコンパイラは関数を呼び出すためのコードを生成し、 "関数が実際にわかったら、この関数のアドレスを記入する"という小さなメモを付けます。

コンパイル単位がこのようにコンパイルされると、一連のオブジェクトファイル(通常はGCCによってコンパイルされた場合は.o、MSVCを使用する場合は.obj)が残されます。空白 "のコード。

リンカはこれらのオブジェクトファイルをすべて取り込み、それらを一緒にマージしようとします。これにより、空白を埋めることができます。上記の呼び出しを生成した関数を見つけることができるので、そのアドレスを呼び出しに挿入することができます。

.cファイルの名前が.hの場合、何も特別なことはありません。これは、人間が各ファイルの内容を簡単に把握できるようにするためのコンベンションです。

コンパイラは気にしません。それぞれの.cファイルに加えて、それに含まれるものをすべて取り、オブジェクトファイルにコンパイルします。リンカは、これらのオブジェクトファイルをすべて1つの実行可能ファイルにマージします。

1

あなたの質問にはちょっとした誤解があります。 * .hファイルに対してコンパイルし、インラインを無視して* .cファイルにリンクします。

  • 「の.h」ファイルは、あなたがに対してコンパイルするために持っているもの、すなわちライブラリへのあなたのインターフェイスであり、かつ
  • マッチング*:あなたは基本に戻ると

    あなたはそれを言うことができます。 Cファイルは、あなたが行うべき機能の実装です。 2つの整数を取り、両者の和である整数を返す

    1. ファイルadd_integers.hだけで関数を宣言し、addIntsは(と言う)、および:
    2. だから、

、一例として、

  • ファイルadd_integers.c(pp)は、2つの整数を取り、それらを合計して結果を返すアルゴリズムを使用するaddInts()関数の実装を提供します。
  • addInts()関数の実装者は、addInts()関数を実装するソフトウェアを自由に変更することができます。

    addInts()関数へのインタフェースが全く変更されていない(addInts.hがまったく変更されていない)場合、addInts関数の変更された実装を含む新しい共有ライブラリは自由に配布できます人々は新しいaddIntsライブラリリリースに対して再コンパイルする必要はありません。

    うわー!なぜこの説明を読むのがDanny Kayeや "The Vessel with the Pessel"のように聞こえるのですか?

    エッフェル塔のBertrand Meyerさんの作品と「Design by Contract」が好きかもしれません。

    0

    CまたはC++で静的ライブラリを作成したい場合は、関数プロトタイプを.hに、実際の関数コードを.cまたは.cppに入れます。私は中の.hが含まれている場合、私の.libに自分の.hをリンクするの.lib

    を作るために私の.cppファイルをコンパイルしている私の後私は.hのその後

    #pragma comment (lib, "theNameOfTheLibFile.lib") 
    

    で、このプリプロセッサコマンドを書きますプログラムでは、私のプログラムは、一致するライブラリをどこに見つけるかを知っています。