为什么我的编译防护不能阻止多个定义包含?

发布于 2024-07-08 07:22:45 字数 589 浏览 9 评论 0原文

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

我在头文件的开头放置了多个包含预防防护,如下所示:

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


#endif//X_H

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

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

  2. #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.

  1. 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?

  2. #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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

天冷不及心凉 2024-07-15 07:22:45

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

#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

C 源文件:

int myFunc()
{
  return 42; 
}

int myVar; 

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.

#ifndef X_H
#define X_H

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

int myVar; // Wrong! definition in header.

#endif

You should split this into source and header file like this:

Header:

#ifndef X_H
#define X_H

extern int myFunc();

extern int myVar; 

#endif

C Source:

int myFunc()
{
  return 42; 
}

int myVar; 
我的影子我的梦 2024-07-15 07:22:45

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

如果您在 xh 中有函数 f 的定义,该函数包含在 main.cutil.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 include stdio.h then guards will help.

If you have the definition of a function f in x.h which is included by main.c and util.c, then it is like copying and pasting the definition of f into main.c when creating main.o and doing the same for util.c to create util.o. Then the linker will complain and this happens despite your header guards. Having multiple #include "x.h" statements in main.c is possible of course because of these guards.

画中仙 2024-07-15 07:22:45

使用包含防护可以防止一个编译单元两次包含标头。 例如,如果标头 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.

乄_柒ぐ汐 2024-07-15 07:22:45

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

If the functions aren't large, you can use "inline" before them and the linker won't complain.

極樂鬼 2024-07-15 07:22:45

使用多重包含保护可以防止编译器错误,但您会收到链接器错误。 头文件中是否有不使用 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?

海风掠过北极光 2024-07-15 07:22:45

也许 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 defines X_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 with CC=gcc CFLAGS="-dM -E" make. If the output file contains #define X_H even though you remove it from your file (use Y_H for example), then it is already defined outside your source code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文