c header-guards 被忽略了?

c header-guards are ignored?

为什么 gcc 在这个简单的测试程序中忽略这些头文件保护?

头文件是:

#ifndef MYHEADER_H
#define MYHEADER_H

#warning "header declared"

int some_int=0;

#endif

而这两个.c文件是: main.c:

#include "header.h"

int main ()
{
    return some_int;
}

source.c:

#include "header.h"

int get_int()
{
    return some_int;
}

编译时:

  gcc -o out main.c source.c

我得到以下输出:

In file included from main.c:1:
header.h:4:2: warning: #warning "header declared" [-Wcpp]
    4 | #warning "header declared"
      |  ^~~~~~~
In file included from source.c:1:
header.h:4:2: warning: #warning "header declared" [-Wcpp]
    4 | #warning "header declared"
      |  ^~~~~~~
/usr/bin/ld: /tmp/ccmAbN1J.o:(.bss+0x0): multiple definition of `some_int'; /tmp/ccEd5PwN.o:(.bss+0x0): first defined here
    collect2: error: ld returned 1 exit status

正如预期的那样,当编译器第一次包含头文件时,会出现警告。但是为什么头球后​​卫不会阻止第二次包含?

gcc 版本为:

gcc version 9.2.1 20200130 (Arch Linux 9.2.1+20200130-2)

Header 防止在单个翻译单元中多次包含(通常是 .c 文件及其直接或间接包含的所有内容)。

您有两个翻译单元,main.csource.c,它们是独立编译的(即使您使用单个命令行 gcc main.c source.c)。这就是为什么您从链接器而不是编译器收到错误消息的原因。

如果你想定义一个object,你应该在.c文件中进行,并在相应的 .h 文件。定义object的.c文件只编译一次,其他多个.c文件可以看到.h文件中的声明。

这不是无视他们。你有两个独立的编译单元,每个都需要 header.h。 Header 守卫旨在防止单个编译单元包含相同的 header 两次。例如。如果main.c包含header.h' directly, but also includedfoo.hwhich also includedheader.h, when all the includes are expanded the header guard ensures thatheader.h`的内容只出现一次。

有 2 个编译单元:1 个用于 main.c,1 个用于 source.c。这些由编译器单独(并且完全独立)编译,产生 2 个目标文件(例如 main.osource.o)。其中每一个都会打印警告:

In file included from main.c:1:
header.h:4:2: warning: #warning "header declared" [-Wcpp]
    4 | #warning "header declared"
      |  ^~~~~~~

然后这些目标文件被链接器链接成可执行文件out

但是链接器发现两个目标文件定义了相同的符号some_int,因此无法生成可执行文件,导致:

/usr/bin/ld: /tmp/ccmAbN1J.o:(.bss+0x0): multiple definition of `some_int'; /tmp/ccEd5PwN.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status