为什么放置 #include 之前包括警卫

Why Placing #include BEFORE include guards

本文关键字:包括警 #include 为什么      更新时间:2023-10-16

是否有任何正当理由在头文件中的包含保护之前放置 #include 指令,如下所示:

#include "jsarray.h"
#include "jsanalyze.h"
#include "jscompartment.h"
#include "jsgcmark.h"
#include "jsinfer.h"
#include "jsprf.h"
#include "vm/GlobalObject.h"
#include "vm/Stack-inl.h"
#ifndef jsinferinlines_h___
#define jsinferinlines_h___
//main body mostly inline functions 
#endif

请注意,这个例子取自一个现实生活中备受瞩目的开源项目,应该由经验丰富的程序员开发 - Firefox 10 中使用的 Mozilla Spidermonkey 开源 Javascript 引擎(最新版本中也存在相同的头文件)。

在备受瞩目的项目中,我希望它们的设计背后一定有一些正当的理由。在包含警卫之前进行#include的正当理由是什么?它是否适用于仅内联函数头文件的模式?另请注意,这个头文件 (jsinferinlines.h) 实际上是通过最后一个 #include "vm/Stack-inl.h" 包含自身(这个头文件包括许多其他头文件,其中一个实际上再次包含这个 jsinferinlines.h)指令之前包含 include guard,这对我来说更没有意义。

因为您希望这些标头包含自己的守卫,因此实际上没有任何区别。

另请注意,这个头文件 (jsinferinlines.h)

实际上是通过最后一个 #include"vm/Stack-inl.h"(这个头文件包含许多其他头文件,其中一个实际上再次包含这个 jsinferinlines.h)指令包含自身,这对我来说更没有意义。

它不会有任何不同,因为包含该文件时,工作流将是:

  • 包括所有标头,最多 "vm/Stack-inl.h"
  • 包括"vm/Stack-inl.h"直到最后#include "jsinferinlines.h"(您的文件)
  • 再次包含文件jsinferinlines.h(跳过所有以前的包含,因为包含保护)
  • 到达过去#include "vm/Stack-inl.h"
  • 最后从#ifndef jsinferinlines_h___开始处理

但总的来说,相互标头递归是不好的,应该不惜一切代价避免。

当时 SpiderMonkey 标头中有很多包含循环,将标头保护放在顶部会导致难以理解的编译错误 - 我怀疑将标头保护放在包含下方只是清理包含的增量步骤。

不过,我无法告诉你导致它发挥作用的确切包含顺序。

如今,SM 标头中不应该有任何包含循环,它们的样式是通过 Nicholas Nethercote 编写的 python 脚本强制执行的。如果你今天看一下jsinferinlines.h,你会看到标题护罩位于它所属的顶部。