2011-10-28 68 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 

当我尝试编译此,海湾合作委员会说,我有多个变量的定义。 ifndef应该确保这不会发生,所以我很困惑它为什么。

+2

*编译器*错误“multiple * declarations *”与* linker *错误“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.c将有something一个实例, main.c将参考它。

+2

您可能还补充说,即使不存在多重定义错误,每个TU都将拥有自己的变量副本,并且不会实现在所有源文件中共享相同变量的目的。 –

3

在每个翻译单元中有一个定义(一个在main.c中,另一个在thing.c中)。标题防护程序会阻止该标题被多次包含在单个翻译单元中。

您需要在头文件中声明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

标题警卫将停止文件编辑不止一次在同一个编译单元(文件)中领导。你将它包含在main.c和thing.c中,所以它将被编译一次,导致变量something在每个单元中被声明一次,或总共两次。

1

变量something应该在头文件中的.c文件中定义,而不是 。

只有变量和函数原型 的结构,宏和类型声明应该在头文件中。在你的例子中,你可以在头文件中声明something的类型为extern int something。但是变量本身的定义应该在.c文件中。

随着你做了什么,变量something将在定义 每个.c文件,其中包括thing.h当GCC试图 一切联系在一起,你得到一个 “的东西定义多次”错误消息。

+0

你的第一个陈述是不正确的。这个变量应该在头文件中声明* extern *关键字,并且在一个唯一的源文件中定义*。 –

1

尽量避免在全局范围内定义变量。 使用像increment()这样的函数来修改和读取它的值。 通过这种方式,您可以将变量static保留在thing.c文件中,并且您确定只有来自该文件的函数才会修改该值。

+0

啊,所以这是你如何避免在C中的全局变量。谢谢你的信息。 – user1007968

0

什么ifndef是守卫是一个.h不止一次包含在.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 =原创海报 –