複数の* .cソースファイルに含まれるヘッダーファイルx.hがあります。このヘッダーファイルには、いくつかの構造変数が定義されています。
ヘッダーファイルの先頭に次のように複数の包含防止ガードを配置しました。
#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.
#endif//X_H
ビルド時に、複数の定義に関連するリンカーエラーが発生します。私は問題を理解しています。
私のようにヘッダーファイルの上部にある複数のインクルード防止ガードは、ヘッダーファイルx.hの複数のインクルードを防ぎ、それによってx.hにある変数の複数の定義を回避しませんか?
#pragma
一度この特定のコンパイラでは機能しないので、解決策は何ですか?誰かが投稿した this 同様の質問への回答。うまくいかないようです。このソリューションはどのように機能しますか?
リンカーが不平を言っている場合は、ヘッダーの宣言だけでなく定義があることを意味します。これは間違っていることの例です。
#ifndef X_H
#define X_H
int myFunc()
{
return 42; // Wrong! definition in header.
}
int myVar; // Wrong! definition in header.
#endif
これをソースとヘッダーファイルに次のように分割する必要があります。
ヘッダ:
#ifndef X_H
#define X_H
extern int myFunc();
extern int myVar;
#endif
Cソース:
int myFunc()
{
return 42;
}
int myVar;
Includeガードを使用すると、1つのコンパイル単位がヘッダーを2回インクルードすることを防ぎます。例えば。ヘッダーB.hにA.hが含まれ、B.cppにA.hとB.hが含まれる場合、インクルードガードを使用していなければ、A.hからのすべてがコンパイルB.cppで2回宣言されます。
インクルードガードはこれが起こらないようにしますが、今までは問題ありません。
しかし、リンク時に複数の定義を取得します。つまり、2つのコンパイルユニットが同じものを定義します。これは、おそらくヘッダーに実際の定義があり、すべての変数にexternを使用し、関数がインラインであるか、cppファイルで定義されていることを確認します。
ヘッダーガードは、単一のコンパイルユニット、つまりソースファイルにのみ適しています。ヘッダーファイルを複数回インクルードした場合、おそらくmain.c
からインクルードされたすべてのヘッダーにstdio.h
がインクルードされている可能性があるため、ガードが役立ちます。
x.h
とmain.c
に含まれるutil.c
の関数f
の定義がある場合、f
をmain.c
に作成してmain.o
を作成し、util.c
を作成してutil.o
を作成します。次に、リンカは文句を言うでしょう、そしてこれはあなたのヘッダーガードにもかかわらずです。これらのガードのため、#include "x.h"
に複数のmain.c
ステートメントを含めることはもちろん可能です。
関数が大きくない場合は、それらの前に「インライン」を使用でき、リンカは文句を言いません。
複数の包含ガードを使用すると、compilerエラーを回避できますが、リンカーエラーが発生します。ヘッダーファイルにextern
を使用しないデータ定義がありますか?
多分X_H
はすでにどこかで定義されていますか? Xlibが/usr/include/X11/X.hでX_H
を定義しているこの問題に遭遇しました。
確認するには、gcc -dM -E
(gccを使用している場合)を呼び出します。私が使用しているビルドシステムでは、CC=gcc CFLAGS="-dM -E" make
で動作します。ファイルからファイルを削除しても(たとえば#define X_H
を使用して)、出力ファイルにY_H
が含まれている場合は、ソースコードの外部ですでに定義されています。