标题/包括警卫不起作用?
出于某种原因,我在头文件中获得了多个内容声明,即使我正在使用标题保护。 我的示例代码如下:
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