2011-10-28 10 views
5

何らかの理由で、ヘッダーガードを使用していても、ヘッダーファイル内に複数の宣言があります。私のコード例は以下の通りです:ヘッダー/インクルードガードが機能しません。

のmain.c:

#include "thing.h" 

int main(){ 
    printf("%d", increment()); 

    return 0; 
} 

thing.c:

#include "thing.h" 

int increment(){ 
    return something++; 
} 

thing.h:

#ifndef THING_H_ 
#define THING_H_ 

#include <stdio.h> 

int something = 0; 

int increment(); 

#endif 

私はこれをコンパイルしようとすると、 GCCは、私は何かの変数の複数の定義を持っていると言います。 ifndefはこれが起こらないことを確認する必要があるので、私はなぜそれが混乱しているのですか。

+2

*コンパイラのエラー "multiple * declarations *"は*リンカ*エラーの "multiple * definitions *"と同じではありません。あなたはあなたの質問に(実際に唯一の問題が後者です)両方を挙げました。その違いを理解することは、何がうまくいかないのかを理解する上で重要です。ヘッダーガードは複数の*宣言*ではなく複数の*宣言*を防ぎます。 – Clifford

+0

@Clifford申し訳ありませんが、私はリンカーのエラーを取得していたと述べたはずです。 – user1007968

+0

また、C 'int increment();はプロトタイプではありませんが、不特定多数のパラメータを持つ関数を宣言しています。それには 'int increment(void);'を使います。 –

答えて

9

インクルードガードが正しく機能しており、問題の原因ではありません。

thing.hを含むすべてのコンパイルユニットが独自のint something = 0を取得するため、リンカーは複数の定義について不満を持ちます。ここで

は、あなたがこの問題を解決する方法である:

thing.c:

#include "thing.h" 

int something = 0; 

int increment(){ 
    return something++; 
} 

thing.h:

#ifndef THING_H_ 
#define THING_H_ 

#include <stdio.h> 

extern int something; 

int increment(); 

#endif 

この方法では、唯一のthing.csomethingのインスタンスを持つことになりますし、 main.cがこれを参照します。

+2

複数の定義エラーがなくても、各TUには独自の変数のコピーがあり、すべてのソースファイルで同じ変数を共有する目的を達成できません。 –

3

各翻訳単位に1つの定義があります(main.cに1つ、thing.cに1つ)。ヘッダーガードは、単一の翻訳単位にヘッダーが複数回含まれないようにします。あなたがに必要

はちょうど関数のように、ヘッダファイルにsomethingを宣言し、だけthing.cでそれをを定義します。

thing.c:

#include "thing.h" 

int something = 0; 

int increment(void) 
{ 
    return something++; 
} 

thing.h:

#ifndef THING_H_ 
#define THING_H_ 

#include <stdio.h> 

extern int something; 

int increment(void); 

#endif 
4

ヘッダーガードは、ファイルがcompiから停止する同じコンパイル単位(ファイル)で2回以上導かれました。あなたはmain.cとthing.cにそれを含めているので、各ユニットで一度コンパイルされ、変数somethingが各ユニットで1回宣言されるか、合計で2回宣言されます。

1

変数somethingは、.cファイルに定義する必要があります。ヘッダファイルには を定義しないでください。

変数および関数プロトタイプ の構造体、マクロ、および型宣言のみがヘッダーファイルに含まれている必要があります。あなたの例では、somethingのタイプをextern int somethingとヘッダファイルに宣言できます。しかし、変数自体の定義は.cファイルでなければなりません。あなたがやっていることで

、変数somethingthing.hを含み、各.cファイルを 定義され、GCCが一緒に すべてをリンクしようとしたとき、あなたは 「何か定義された複数回の」エラーメッセージが表示されます。

+0

あなたの最初のステートメントは間違っています。変数はヘッダーファイルで* extern *キーワードで宣言*し、唯一のソースファイルで*定義*する必要があります。 –

1

変数をグローバルに定義しないようにしてください。 インクリメント()のような関数を使用して、その値を変更して読み込みます。 そのようにすれば、変数staticをthing.cファイルに保持することができ、そのファイルの関数だけが値を変更することがわかります。

+0

ああ、これはCでグローバル変数を避ける方法です。情報をありがとうございます。 – user1007968

0

何がifndefであるかは、.cに複数含まれています。.hです。例えば

ものです。時間

#ifndef 
#define 

int something = 0; 
#endif 

thing2.h

#include "thing.h" 

main.cの

#include "thing.h" 
#include "thing2.h" 
int main() 
{ 
    printf("%d", something); 
    return 0; 
} 

私はifndefを残すかどうか、その後GCCが文句を言うでしょう

In file included from thing2.h:1:0, 
      from main.c:2: 
thing.h:3:5: error: redefinition of ‘something’ 
thing.h:3:5: note: previous definition of ‘something’ was here 
+0

あなたの説明は間違いありませんが、OPの問題はそうではありませんが、包括ガードは間違いなく*インプレース*です。 –

+0

@Als申し訳ありませんが、OP? – manuzhang

+0

OP =オリジナルのポスター –

関連する問題