62

我有一个头文件 xh,它包含在多个 *.c 源文件中。这个头文件定义了一些结构变量。

我在头文件的开头放置了多个包含防止保护:

#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.


#endif//X_H

在构建时,我得到与多个定义相关的链接器错误。我明白这个问题。

  1. 不会像我一样在头文件顶部设置多重包含防止保护,防止头文件 xh 的多重包含,从而避免 xh 中存在的变量的多个定义?

  2. #pragma一次在这个特定的编译器上不起作用,那么解决方案是什么?有人将这个答案发布到了类似的问题上。它似乎对我不起作用。这个解决方案是如何工作的?

4

6 回答 6

82

如果链接器在抱怨,这意味着您有定义,而不仅仅是标题中的声明。这是一个错误的例子。

#ifndef X_H
#define X_H

int myFunc()
{
  return 42; // Wrong! definition in header.
}

int myVar; // Wrong! definition in header.

#endif

您应该将其拆分为源文件和头文件,如下所示:

标题:

#ifndef X_H
#define X_H

extern int myFunc();

extern int myVar; 

#endif

来源:

int myFunc()
{
  return 42; 
}

int myVar; 
于 2008-10-30T10:15:11.377 回答
21

标头保护仅适用于单个编译单元,即源文件。如果您碰巧多次包含一个头文件,也许是因为main.c依次包含的所有头文件都包含,stdio.h那么守卫会有所帮助。

如果你有一个包含在and中的函数f的定义,那么它就像在创建时复制并粘贴到的定义和对创建执行相同的操作一样。然后链接器会抱怨,尽管您有标头保护,但仍然会发生这种情况。由于这些守卫,当然可以有多个语句。x.hmain.cutil.cfmain.cmain.outil.cutil.o#include "x.h"main.c

于 2012-03-06T00:24:13.870 回答
15

使用包含防护可以防止一个编译单元包含两次标头。例如,如果头文件 Bh 包含 Ah 并且 B.cpp 包含 Ah 和 Bh,如果您不使用包含守卫,则来自 Ah 的所有内容将在编译 B.cpp 中声明两次。

您的包含警卫防止这种情况发生,到目前为止一切都很好。

但是你在链接时得到了多个定义,即两个编译单元定义了同一个东西,这可能意味着你在你的头文件中有一个真正的定义,对所有变量使用 extern,确保函数是内联的或在 cpp 文件中定义。

于 2008-10-30T10:01:32.527 回答
12

如果函数不大,您可以在它们之前使用“内联”,链接器不会抱怨。

于 2010-07-16T23:05:26.360 回答
2

使用多重包含保护可防止编译器错误,但您会遇到链接器错误。头文件中是否有不使用的数据定义extern

于 2008-10-30T09:56:16.483 回答
0

也许X_H已经在其他地方定义了?我刚刚遇到了这个问题,XlibX_H在 /usr/include/X11/Xh中定义

要检查,您可以调用gcc -dM -E(如果您使用 gcc),例如在我正在使用的构建系统中调用CC=gcc CFLAGS="-dM -E" make. 如果输出文件包含#define X_H即使您从文件中删除它(Y_H例如使用),那么它已经在您的源代码之外定义。

于 2012-09-21T13:35:24.830 回答