标题/包括警卫不起作用?

出于某种原因,我在头文件中获得了多个内容声明,即使我正在使用标题保护。 我的示例代码如下:

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  int something = 0; int increment(); #endif 

当我尝试编译它时,GCC说我对some变量有多个定义。 ifndef应该确保不会发生这种情况,所以我很困惑为什么会这样。

包含警卫function正常,不是问题的根源。

会发生的是,包含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  extern int something; int increment(); #endif 

这样,只有thing.c会有一个实例,而main.c会引用它。

标题保护将阻止文件在同一编译单元(文件)中多次编译。 你将它包含在main.c和thing.c中,因此它将在每个单元中编译一次,导致变量在每个单元中声明一次,或者总共两次。

每个翻译单元都有一个定义(一个在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  extern int something; int increment(void); #endif 

尽量避免全局定义变量。 使用increment()之类的函数来修改和读取它的值。 这样你可以将变量静态保存在thing.c文件中,并且你确定只有该文件中的函数才会修改该值。

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

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

有了你所做的,变量将在包含thing.h 每个 .c文件中定义,并且当GCC尝试将所有内容链接在一起时,您会收到“多次定义的内容”错误消息。

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