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

时间:2016-07-15 06:08:04

标签: c++ c-preprocessor include-path

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

但现在我想知道:我是否正确学习,或者实际上是否还有预处理器的标准?

3 个答案:

答案 0 :(得分:3)

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

话虽如此,如果某个实现想要编译现有源代码的任何希望,最好遵循与其余的相同的约定:<...>引用系统包含文件,"..."引用到您自己的包含文件(首先应搜索包含源文件的目录)。这些都不是标准的要求,但如果没有它们,你就无法编译任何现有的代码。

标准在某些地方有点精神分裂 - 在一个地方它会为你提供处理文件和目录的工具(C ++ 17中的文件系统扩展),而在其他地方,它拒绝承认像文件和文件这样的东西。目录甚至存在。据推测,这是因为作者不想过多地使用古代文本,因为它现在工作正常,可能只是偶然破坏了东西,但它看起来确实有点滑稽。

答案 1 :(得分:2)

为了扩展H. Gujit的答案,C或C ++语言标准都没有提供任何保证,但 POSIX 标准确实提供了一些关于如何cpp的额外保证( C P 重新 p rocessor)将起作用。 For instance, in the description of the -I command line option

  

因此,名称以双引号("")括起来的标题应首先在#include行的文件目录中搜索,然后在-I中命名的目录中搜索选项,并在通常的地方持续。对于名称用尖括号括起来的标题(&#34; <>&#34;),标题只能在-I选项中命名的目录中搜索,然后才能在通常的位置搜索。 / p>

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

答案 2 :(得分:1)

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

  

标题中搜索一系列实现定义的位置   由<>之间的指定序列唯一标识   分隔符。如何指定地点或标识的标题是   实现定义。 [强调补充]

相反(16.2 [cpp.include] / 3),#include "..."

  

导致该指令被整个内容替换   源文件"分隔符之间的指定序列标识。在一个中搜索指定的源文件   实现定义的方式。如果不支持此搜索,或者搜索失败,则会重新处理该指令,就像它读取一样   #include <...>   使用相同的包含序列(包括>个字符,如果有的话)来自原始指令。 [强调补充]

因此,定位完全的位置和技术除外,如果在初始搜索中找不到源文件,则#include "..."会返回#include <...>

措辞的不同之处很重要:#include <...> 需要源文件;它完全取决于它如何处理标准头文件的实现。用户编写的标题文件应 加入#include "...",因为这是处理源文件所需的文件。

在大多数情况下,编译器会以您期望的方式实现这些功能。您在MSVC中看到的关键区别在于#include "..."它首先在正在编译的顶级源文件的目录中搜索,而其他编译器首先在目录中搜索当前正在编译的源文件。当头文件具有#include "..."指令时,这很重要:大多数编译器在头文件所在的目录中搜索,但MSVC搜索好像#include "..."指令在顶级源文件中。两者都是有效的,并且这两种方法都存在争议,尽管我个人觉得搜索标题更直观,更易于使用的目录。