为什么编译器默认不自动添加或生成包含保护?

Why doesn't the compiler automatically add or generate an include guard by default?

我知道 C 或 C++ 代码通常需要像这样使用 include guards:

#ifndef __A__H__
#define __A__H__
class A{
};
#endif

为了加快编译速度,在其他cpp中(例如:B.cpp),可以改成

#include "A.h"

至:

#ifndef __A__H__
#include "A.h"
#endif

但问题是为什么编译器不自动添加或生成include guard,因此如果通常需要include guard,为什么还要程序员手动添加呢?

有时候生成 header 守卫是绝对不正确的。标准包含一个示例:C 中的 <assert.h> 和 C++ 中的 <cassert>

重新包含那些 header 的效果取决于(重新)包含 header 时 NDEBUG 宏的状态。合法的写法:

#undef NDEBUG
#include <assert.h>
…code using assert…
#define NDEBUG 1
#include <assert.h>
…more code using assert…

如果编译器自动生成 header 守卫,那将无法正常工作。因此,编译器不会自动生成 header 守卫。


顺便说一下,用户代码不应使用 header 以双下划线或下划线大写字母开头的保护宏名称。这些名称保留用于实现。在 C++ 中,任何 user-defined 名称都不能合法地包含双下划线。使用更像:

#ifndef A_H_INCLUDED
#define A_H_INCLUDED
…body of header…
#endif

编译器,或者更严格地说,预处理器无法确定程序员使用包含的意图。编译器没有明确区分 .h 文件和 .c 或 .cpp 文件;它们仅在放置在其中的代码类型上有所不同。事实上,编译器只处理一个 翻译单元 ; C 预处理器负责将所有包含的文件连接到一个文件中进行编译。预处理器忽略它之前包含的包含是不正确的,因为它没有代码的语义知识,并且可能会因对开发人员的事后猜测而导致预期行为发生变化。

在某些情况下,IDE 可能会为其生成的模板代码添加包含保护。例如,Microsoft Visual Studio 将为通过其项目启动向导生成的代码添加它们。如果真的发生了,这完全是 IDE 的责任,而不是编译器或预处理器的责任。