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.c
和 source.c
,它们是独立编译的(即使您使用单个命令行 gcc main.c source.c
)。这就是为什么您从链接器而不是编译器收到错误消息的原因。
如果你想定义一个object,你应该在.c
文件中进行,并在相应的 .h
文件。定义object的.c
文件只编译一次,其他多个.c
文件可以看到.h
文件中的声明。
这不是无视他们。你有两个独立的编译单元,每个都需要 header.h
。 Header 守卫旨在防止单个编译单元包含相同的 header 两次。例如。如果main.c
包含header.h' directly, but also included
foo.hwhich also included
header.h, when all the includes are expanded the header guard ensures that
header.h`的内容只出现一次。
有 2 个编译单元:1 个用于 main.c
,1 个用于 source.c
。这些由编译器单独(并且完全独立)编译,产生 2 个目标文件(例如 main.o
和 source.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
为什么 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.c
和 source.c
,它们是独立编译的(即使您使用单个命令行 gcc main.c source.c
)。这就是为什么您从链接器而不是编译器收到错误消息的原因。
如果你想定义一个object,你应该在.c
文件中进行,并在相应的 .h
文件。定义object的.c
文件只编译一次,其他多个.c
文件可以看到.h
文件中的声明。
这不是无视他们。你有两个独立的编译单元,每个都需要 header.h
。 Header 守卫旨在防止单个编译单元包含相同的 header 两次。例如。如果main.c
包含header.h' directly, but also included
foo.hwhich also included
header.h, when all the includes are expanded the header guard ensures that
header.h`的内容只出现一次。
有 2 个编译单元:1 个用于 main.c
,1 个用于 source.c
。这些由编译器单独(并且完全独立)编译,产生 2 个目标文件(例如 main.o
和 source.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