为什么我的编译防护不能阻止多个定义包含?
我有一个头文件 xh,它包含在多个 *.c 源文件中。 该头文件定义了一些结构变量。
我在头文件的开头放置了多个包含预防防护,如下所示:
#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.
#endif//X_H
在构建时,我收到与多个定义相关的链接器错误。 我明白这个问题。
不会像我一样在头文件顶部设置多重包含预防防护,防止头文件 xh 的多重包含,从而避免 xh 中变量的多重定义吗?
#pragma
Once 在这个特定的编译器上不起作用,那么解决方案是什么? 有人发布了此回答类似的问题。 这似乎对我不起作用。 这个解决方案如何工作?
I have a header file x.h which is included by more than one *.c source files.
This header file has some structure variables defined.
I have put multiple inclusion prevention guard at the beginning of the header file as:
#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.
#endif//X_H
On building I get linker errors related to multiple definitions. I understand the problem.
Won't a multiple inclusion prevention guard at the top of header file as I have, prevent multiple inclusions of the header file x.h and thereby avoid multiple definitions of the variables that are there in x.h?
#pragma
once does not work on this particular compiler, so what is the solution?
Someone had posted this answer to a similar question. It doesn't seem to work for me. How does this solution work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果链接器抱怨,则意味着您的标头中有定义而不仅仅是声明。 这是一个错误的例子。
您应该将其分成源文件和头文件,如下所示:
头文件:
C 源文件:
If the linker is complaining, it means you have definitions rather than just declarations in your header. Here's an example of things that would be wrong.
You should split this into source and header file like this:
Header:
C Source:
标头保护仅适用于单个编译单元,即源文件。 如果您碰巧多次包含一个头文件,可能是因为从
main.c
包含的所有头文件又包含stdio.h
那么守卫会有所帮助。如果您在
xh
中有函数f
的定义,该函数包含在main.c
和util.c
中,那么就像在创建main.o
时将f
的定义复制并粘贴到main.c
中,并对执行相同的操作util.c
创建util.o
。 然后链接器会抱怨,尽管你有头保护,但这种情况还是会发生。 由于这些保护措施,在main.c
中拥有多个#include "xh"
语句当然是可能的。Header guards are only good for a single compilation unit, i.e., source file. If you happen to include a header file multiple times, perhaps because all headers included from
main.c
in turn includestdio.h
then guards will help.If you have the definition of a function
f
inx.h
which is included bymain.c
andutil.c
, then it is like copying and pasting the definition off
intomain.c
when creatingmain.o
and doing the same forutil.c
to createutil.o
. Then the linker will complain and this happens despite your header guards. Having multiple#include "x.h"
statements inmain.c
is possible of course because of these guards.使用包含防护可以防止一个编译单元两次包含标头。 例如,如果标头 Bh 包含 Ah 并且 B.cpp 包含 Ah 和 Bh,则如果您不使用包含防护,则 Ah 中的所有内容都将在编译 B.cpp 中声明两次。
你的包含守卫阻止了这种情况的发生,到目前为止一切都很好。
但是您在链接时获得多个定义,即两个编译单元定义相同的内容,这可能意味着您在标头中获得了真正的定义,对所有变量使用 extern,确保函数是内联的或在 cpp 文件中定义的。
Using include guards prevents one compilation unit from including the header twice. E.g. if header B.h includes A.h and B.cpp includes A.h and B.h, everything from A.h would be declared twice in the compilation B.cpp if you weren't using include guards.
Your include guards prevent this from happening, all's fine till now.
But you get multiple definitions at link time, i.e. two compilation units define the same thing, this probably means you got a real definition in your header, use extern for all variables, make sure functions are either inline or are defined in the cpp file.
如果函数不大,您可以在它们之前使用“inline”,链接器不会抱怨。
If the functions aren't large, you can use "inline" before them and the linker won't complain.
使用多重包含保护可以防止编译器错误,但您会收到链接器错误。 头文件中是否有不使用
extern
的数据定义?Using a multiple inclusion guard prevents compiler errors, but you're getting a linker error. Do you have data definitions in the header file that don't use
extern
?也许
X_H
已经在其他地方定义了? 我刚刚遇到这个问题,其中 Xlib 在 /usr/include/X11/Xh 中定义了X_H
要检查,您可以调用
gcc -dM -E
(如果您使用的是gcc),例如在我正在使用的构建系统中,它与CC=gcc CFLAGS="-dM -E" make
一起使用。 如果输出文件包含#define X_H
,即使您将其从文件中删除(例如使用Y_H
),则它已在源代码外部定义。Maybe
X_H
is already defined somewhere else? I just ran into this issue, where Xlib definesX_H
in /usr/include/X11/X.h.To check, you can call
gcc -dM -E
(if you are using gcc), e.g. in the buildsystem I’m using that works withCC=gcc CFLAGS="-dM -E" make
. If the output file contains#define X_H
even though you remove it from your file (useY_H
for example), then it is already defined outside your source code.