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

时间:2011-10-28 07:16:21

标签: c header include-guards

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

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说我对some变量有多个定义。 ifndef应该确保不会发生这种情况,所以我很困惑为什么会这样。

6 个答案:

答案 0 :(得分:10)

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

包含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会引用它。

答案 1 :(得分:4)

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

答案 2 :(得分:3)

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

您需要在头文件中声明 something,并且只在<{1}}中定义,就像函数一样:

thing.c:

thing.c

thing.h:

#include "thing.h"

int something = 0;

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

答案 3 :(得分:1)

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

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

通过您所做的工作,将定义变量something包含.c的每个 thing.h文件中,您获得了一个 GCC尝试链接时出现“多次定义的内容”错误消息 一切都在一起。

答案 4 :(得分:1)

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

答案 5 :(得分:0)

ifndef所守护的是.h中不止一次包含.c的{​​{1}}。例如

的事情。 ħ

#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