13

.hファイルと.cファイルのリンクに問題があります。この問題に関するスレッドもいくつか読んでいますが、それらはすべて少しあいまいですが、それでもその概念を完全に理解することはできません。また、リンクの問題がたくさんあります。 、私がacで使用するbcとbhを持っていて、bhをacとbcの両方に含めるかどうか混乱しているとしましょう。cuzbc自体がbhで定義された構造を知る必要があります。私は、bhでプロトタイプを持ち、定義されている関数を持っています。 bhの構造も使用するbcでは、imはbc cuzにbhを含めていません。これは、bhがbcの関数を使用するacへのインターフェイスに似ていることを知っているためです。ここでより明確な例

bhファイル

typedef struct{
int x, y;
}myStruct;

void funct1(myStruct);
void funct2(myStruct);

bcファイル

void funct1(myStruct x)
{
    //do something
}

void funct2(myStruct y)
{
     //do something
} 

acファイル

#include "b.h"

int main()
{
myStruct x;
  funct1(x);
  funct2(y);
return 0;
}

cygwinでコマンドを実行しました:gcc bc ac -g

紛らわしい部分ですが、リンクエラーが発生しました。bcをコンパイルすると、bh Cuzの構造とプロトタイプを検出できません。私が知っているのは、bhを使用してacからbcをリンクすることだけですが、両方の.cをコンパイルすると、そのbcはその構造とプロトタイプを見つけることができません、

なぜbcにbhを含めなかったのですか? 回答:Cuzは私が知っていることですが、bhはすでにacに含まれており、bcに再び含めると、ダブルインクルージョンを実行します<---これまでに学んだことであり、#ifdefがあることはわかっていますが、それはうまくいきません、多分私はまだそれを使う方法を知りません、あなたが知っているならば、これについて気軽に話し合ってください。

これをどうやって進めるかについて何か考えがあれば、遠慮なく教えてください。

#ifdefディレクティブがありますが、これを行う方法がわからないようです。

注:上記のすべてのコードが構文的に正しいと仮定します。スペルミスのある単語がある場合は無視してください。私は.hと.cの間にインクルードした後のみです。

4

4 に答える 4

30

あなたは確かにする必要があり#include b.hますb.c。各ファイルは、リンカが引き継ぐ前に個別にコンパイルされます。したがって、bcはそれ自体でコンパイルされ、bhを含めない限り、bhの内容を認識しないため、acにbhを含めても問題ありません。

#includeこれが警備員の例です

// some_header_file.h
#ifndef SOME_HEADER_FILE_H
#define SOME_HEADER_FILE_H
// your code
#endif

some_header_file.hがどこかにインクルードされている場合、SOME_HEADER_FILE_Hが定義されていれば、#ifndefとの間のすべて#endifが無視されます。これは、コンパイルユニットに初めてインクルードされたときに発生します。

#defineプロジェクト内での一意性を確保するために、ファイル名にちなんで名前を付けるのが一般的な方法です。他のコードとの衝突のリスクを減らすために、プロジェクトまたは名前空間の名前もプレフィックスとして付けるのが好きです。

注:上記のインクルードガードを使用しても、同じヘッダーファイルをプロジェクト内に複数回インクルードできます。同じコンパイルユニット内に2回インクルードすることはできません。これは次のように示されます。

// header1.h
#ifndef HEADER_H
#define HEADER_H
int test1 = 1;
#endif

// header2.h
#ifndef HEADER_H
#define HEADER_H
int test2 = 2;
#endif

次に、上記の2つのファイルをインクルードしようとするとどうなるか見てみましょう。単一コンパイル単位の場合:

// a.cpp
#include "header1.h"
#include "header2.h"
#include <iostream>
int main()
{
   std::cout << test1;
   std::cout << test2;
};

test2が定義されていないため、これによりコンパイラエラーが生成されます。HEADER_Hは含まれている時間までにすでに定義されているため、header2.hでは無視されます。ここで、各ヘッダーを別々のコンパイル単位に含めると、次のようになります。

// a.cpp
#include "header2.h"
int getTest2()
{
   return test2;
};

// b.cpp
#include "header1.h"
#include <iostream>
int getTest2(); // forward declaration
int main()
{
   std::cout << test1;
   std::cout << getTest2();
};

両方ともHEADER_Hを定義する2つのファイルが含まれている場合でも、正常にコンパイルされ、期待される出力(1と2)が生成されます。

于 2013-01-12T03:54:31.353 に答える
3

b.hで定義されている構造を使用するすべてのファイルに含める必要がありますb.h#include <b.h>したがって、両方のファイルにを入れる必要があります。それが数回ロードされるのを避けるためにb.h、ディレクティブが必要です#ifdef。あなたの場合:

bh

#ifndef B_H
#define B_H

typedef struct{
    int x, y;
}myStruct;

void funct1(myStruct);
void funct2(myStruct);

#endif

およびbc:

#include "b.h"

void funct1(myStruct x)
{
    //do something
}

void funct2(myStruct y)
{
     //do something
} 
于 2013-01-12T03:56:36.157 に答える
1

適切なコーディングでは、bcにbhを含める必要があります

動作するはずのヘッダーガードは次のとおりです。

#ifndef B_H_INCLUDED
#define B_H_INCLUDED
//header file
#endif

コメントがある場所に宣言を置き、必要な場所にすべて含めます。

編集私が理解しているように、gccacはbcに依存しているため、最初にbcをコンパイルします。しかし、bcを最初にコンパイルするとき、bhはまだ含まれていません

于 2013-01-12T03:53:47.387 に答える
0

bcでbhを実行する必要があります#include。これはacのインターフェイスだけでなく、bcは独自のコードについても同じ定義を知っている必要があります。bcにbhを含めない理由は間違っています。各.cファイルは、他のすべての.cファイルとは別にコンパイルされます。コンパイラがacで実行されると、bcで最初からやり直します。bcにはacが存在するという概念がないため、acにbhが含まれていても問題ありません。ヘッダーガードの目的は、特定の.cファイルのコンパイル中に.hファイルが複数回インクルードされた場合に、.hファイルが繰り返し処理されないようにすることです。ガードがないと、宣言が複数回コンパイルされ、既存のシンボルの複数の宣言に関するエラーが発生します。

于 2013-01-12T04:00:23.490 に答える