c标头保护被忽略



为什么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;
}

来源: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(。这就是为什么您从链接器而不是编译器获得错误消息的原因。

如果要定义对象,则应在.c文件中进行定义,并在相应的.h文件中将其声明为extern。定义对象的.c文件只编译一次,其他多个.c文件可以在.h文件中看到声明。

它不会忽略它们。您有两个独立的编译单元,每个单元都需要header.h。标头保护旨在防止单个编译单元两次包含同一标头。例如如果main.c包含header.h' directly, but also included foo.h which also included header.h , when all the includes are expanded the header guard ensures that header.h的内容只出现一次。

有两个编译单元: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

相关内容

  • 没有找到相关文章

最新更新