C++ #include 查找是否有任何标准要求?

Is there any standard requirement for C++ #include lookup?

最近 I learned gnu cpp 和 msvc cl 以不同方式处理 #include 文件。常见的行为是查看 includ_ing_ 文件旁边的目录,然后遍历包含路径(这显然是使用 -I/I 编译器参数设置的。)

但现在我想知道:我是否学对了,或者预处理器实际上也有一个标准吗?

根据标准,#include <...>#include "..." 都应搜索实现定义的位置集。甚至不要求 <>"" 之间提供的名称是文件名,只是它允许唯一标识 header.

话虽如此,如果一个实现希望编译现有源代码,它最好遵循与其他相同的约定:<...> 指系统包含文件,"..."指的是你自己的include文件(应该先搜索包含源文件的目录)。 None 其中是标准的要求,但如果没有它们,您将无法编译几乎所有现有代码。

该标准在某些地方有点精神分裂 - 在一个地方它会为您提供处理文件和目录的工具(C++17 中的文件系统扩展),而在其他地方它拒绝承认诸如文件和目录甚至存在。大概是因为作者不想把古文字搞得太多,因为它现在工作正常,可能只是不小心破坏了一些东西,但它看起来确实有点滑稽。

为了扩展 H. Gujit 的回答,C 或 C++ 语言标准均未在此处提供任何保证,但 POSIX 标准确实提供了一些额外的保证cppCPrep处理器)应正常运行。 For instance, in the description of the -I command line option:

Thus, headers whose names are enclosed in double-quotes ( "" ) shall be searched for first in the directory of the file with the #include line, then in directories named in -I options, and last in the usual places. For headers whose names are enclosed in angle brackets ( "<>" ), the header shall be searched for only in directories named in -I options and then in the usual places.

So any UNIX-like platforms attempting POSIX compliance will behave in this way.

按照标准(16.2[cpp.include]/2),#include <...>

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters. How the places are specified or the header identified is implementation-defined. [emphasis added]

对比(16.2[cpp.include]/3),#include "..."

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read #include <...> with the identical contained sequence (including > characters, if any) from the original directive. [emphasis added]

所以位置和技术 完全 实现定义,除了如果在初始搜索中没有找到源文件 #include "..." 回退到 #include <...> .

措辞上的差异很重要:#include <...> 不需要 需要源文件;如何处理标准 headers 完全取决于实现。 User-written header 文件应该 被拉入 #include "...",因为这是处理源文件所需要的文件。

在大多数情况下,编译器以您期望的方式实现这些东西。您在 MSVC 中看到的关键区别在于,对于 #include "...",它首先在正在编译的 top-level 源文件的目录中搜索,而其他编译器首先在正在编译的源文件的目录中搜索目前正在编制中。当 header 文件有 #include "..." 指令时,这很重要:大多数编译器在 header 文件所在的目录中搜索,但 MSVC 搜索时就好像 #include "..." 指令在top-level 源文件。两者都是有效的,并且对这两种方法都有争论,尽管我个人发现搜索 header 所在的目录更直观,更容易使用。