C头文件包括仅在头文件中使用的保护,但不在.C文件中使用。为什么?

C头文件包括仅在头文件中使用的保护,但不在.C文件中使用。为什么?,c,header,include-guards,C,Header,Include Guards,我在头文件中使用防护已经有一段时间了,我理解为什么使用防护的唯一原因是为了在编译时允许单个包含此(头文件中考虑了防护) 我想知道使用标题保护是否还有其他原因,为什么在.c文件中不使用它们,如果保护也用于.c文件会发生什么 答:从下面的回答中收集 通常所有的定义都放在.c文件中,头文件(.h文件)包含所有的声明。包含.c文件不是一个好的做法 为了在编译时仅与一个特定于翻译单元的.c文件中可用的声明的一个包含相关联(因此,如果有两个或多个库需要链接;即,我们有两个或多个翻译单元);头保护有助于只包含

我在头文件中使用防护已经有一段时间了,我理解为什么使用防护的唯一原因是为了在编译时允许单个包含此(头文件中考虑了防护)

我想知道使用标题保护是否还有其他原因,为什么在.c文件中不使用它们,如果保护也用于.c文件会发生什么

答:从下面的回答中收集

通常所有的定义都放在.c文件中,头文件(.h文件)包含所有的声明。包含.c文件不是一个好的做法

为了在编译时仅与一个特定于翻译单元的.c文件中可用的声明的一个包含相关联(因此,如果有两个或多个库需要链接;即,我们有两个或多个翻译单元);头保护有助于只包含一次头文件


这是因为预处理器阶段甚至在编译文件以获取对象(.o扩展名)文件之前。“预处理器”阶段将替换整个宏并包含相关数据,这样只允许包含一次.h文件。

标题保护所做的不是防止在一个项目中包含多个,而是仅在一个项目中包含

例如,假设您有两个头文件,
a.h
b.h
。头文件
b.h
包括
a.h
,然后
a.h
b.h
都包括在源文件
s.c
中。如果没有标题保护,文件
a.h
将包含两次,这可能会导致错误。如果头文件有头保护,那么文件
a.h
将只包含一次


源文件中不需要头保护,因为通常不在其他文件中包含它们。

头保护的主要目的是避免重复包含

考虑下面的例子

在编译单元中有以下头文件

example_1.h
example_2.h (includes example_1.h)
在“C”文件中,包括
'example_1.h'
'example_2.h'
语句(宏)

“#include example_1.h”
将执行两次

当您添加行时

#ifdef EXAMPLE_1
#define EXAMPLE_1


#endif
对于示例_1.h,当您第一次遇到#include example_1.h时,您会告诉您编译系统,请定义一个宏(该宏是构建系统的本地宏),它向我表明我在下次遇到示例_1.h时已经包含了该宏
\include example_1.h
我将看到
example_1
确实是在构建系统中定义的 然后跳过


对于一个小例子来说,这似乎是一件小事,但在有数百个文件的大型项目中,这确实是一个非常有用的功能。而且由于
.c文件
不会被其他文件包含,因此将它们包含在
.c文件

下并没有任何意义,谢谢Joachim的回复。但是,如果真的有这样一种情况,我需要在.c文件中使用警卫,那么这种情况什么时候会出现呢?@AditYa在真正的初学者圈子之外(在那里,
#通常包括
源文件,而不是单独编译它们)我所看到的包含源文件的案例都是经过精心准备的,这样它们就不会在一个翻译单元中包含两次,也就不需要头保护了。作为一般规则:不要包含源文件!那么您就不必担心了。@AditYa如果出于某种原因决定使用约定
myheaderfile.c
命名头文件,那么您将为该文件使用包含保护。毕竟,名称中的
.c
纯粹是一个约定(但显然是一个好约定)。如果您编写
#include“foo.h”
两次,那么foo.h的内容将包含两次。这就是你需要警卫的原因。现在假设您已经编写了“bar.c”,并且出于某种原因让构建脚本编译它两次。第一次编译时,它将生成
bar.o
,第二次编译时,它将再次覆盖
bar.o
。这就是为什么源文件不需要任何类型的保护。