8

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

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

4

6 回答 6

12

包含防护功能正常,不是问题的根源。

发生的情况是每个包含的编译单元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会引用它。

于 2011-10-28T07:24:57.157 回答
4

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

您需要在头文件中声明 ,并且只在 中定义,就像函数一样:somethingthing.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
于 2011-10-28T07:25:09.897 回答
4

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

于 2011-10-28T07:25:41.730 回答
1

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

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

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

于 2011-10-28T07:30:02.557 回答
1

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

于 2011-10-28T07:33:02.933 回答
0

什么ifndef是守卫是一个不止一次.h包含在一个中。.c例如

事物。H

#ifndef
#define

int something = 0;
#endif

东西2.h

#include "thing.h"

主程序

#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
于 2011-10-28T07:37:51.857 回答