由于某种原因,即使我使用标头防护,我也会在标头文件中收到多个内容声明。我的示例代码如下:
main.c:
#include "thing.h"
int main(){
printf("%d", increment());
return 0;
}
东西.c:
#include "thing.h"
int increment(){
return something++;
}
东西.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
int something = 0;
int increment();
#endif
当我尝试编译此文件时,GCC 说我对 some 变量有多个定义。 ifndef 应该确保这种情况不会发生,所以我很困惑为什么会这样。
包含防护功能正常,不是问题的根源。
发生的情况是,包含
thing.h
的每个编译单元都有自己的 int something = 0
,因此链接器会抱怨多个定义。
解决此问题的方法如下:
东西.c:
#include "thing.h"
int something = 0;
int increment(){
return something++;
}
东西.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
extern int something;
int increment();
#endif
这样,只有
thing.c
才会有 something
的实例,并且 main.c
才会引用它。
每个翻译单元都有一个定义(一个在
main.c
中,一个在 thing.c
中)。标头防护装置可防止标头多次包含在单个翻译单元中。
你需要在头文件中声明
something
,并且只需要在thing.c
中定义,就像函数一样:
东西.c:
#include "thing.h"
int something = 0;
int increment(void)
{
return something++;
}
东西.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
extern int something;
int increment(void);
#endif
标头防护将阻止文件在同一编译单元(文件)中被多次编译。您将其包含在 main.c 和 thing.c 中,因此它将在每个单元中编译一次,从而导致变量
something
在每个单元中声明一次,或者总共声明两次。
尽量避免全局定义变量。 使用像increment()这样的函数来修改和读取它的值。 这样您就可以在 thing.c 文件中保持变量静态,并且您可以确定只有该文件中的函数才会修改该值。
变量
something
应该定义在 .c
文件中,而不是
在头文件中。
仅变量和函数原型的结构、宏和类型声明 应该在头文件中。在您的示例中,您可以在头文件中将
something
的类型声明为 extern int something
。但变量本身的定义应该在 .c
文件中。
完成后,变量
something
将被定义
在包含 .c
的 each
thing.h
文件中,你会得到一个
GCC 尝试链接时出现“多次定义的内容”错误消息
一切都在一起。
ifndef
所守护的是一个.h
多次包含在.c
中。例如东西。
#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