【问题标题】:Is there any standard requirement for C++ #include lookup?C++ #include 查找是否有任何标准要求?
【发布时间】:2016-11-18 05:47:18
【问题描述】:

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

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

【问题讨论】:

  • 标准甚至不谈论源文件
  • 而且托管文件系统甚至没有目录要求,所以很难标准化。
  • 这些编译器有什么不同?
  • @MatteoItalia,用词不当。 [lex.separate] 定义“源文件”,[cpp] 讨论如何包含它们。它可能会以与您略有不同的方式使用它们,但它肯定确实谈论它们。

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


【解决方案1】:

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

话虽如此,如果一个实现想要编译现有源代码,它最好遵循与其余部分相同的约定:<...> 指的是系统包含文件,"..." 指的是您自己的包含文件(应首先搜索包含源文件的目录)。这些都不是标准的要求,但是没有它们,您将无法编译几乎所有现有代码。

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

【讨论】:

  • #include "..." 需要源文件。 #include <...> 指的是一个 header,它 not 必须是源文件。
  • @PeteBecker 我认为你的意思是相反的。
  • 不。请参阅我的答案,其中列出了标准中的文本。
  • 好吧,在这种情况下,你完全错了。根据您引用的文本,"..." 可能指的是源文件或标题 - 不需要它是源文件。 <...> 指的是一个标头,而且只是一个标头。
  • 哦,我明白你的意思了。但这不是“反过来”,只是我夸大了#include "..." 的要求。顺便说一句,这个答案没有提到的要求。
【解决方案2】:

为了扩展 H. Gujit 的回答,C 或 C++ 语言标准都没有提供任何保证,但 POSIX 标准确实提供了一些关于 cppC Prep处理器)应起作用。 For instance, in the description of the -I command line option:

因此,名称用双引号 ("") 括起来的标题应首先在具有#include 行的文件目录中搜索,然后在以-I 选项命名的目录中搜索,最后在通常的地方。对于名称包含在尖括号 ( "<>" ) 中的标头,应仅在以 -I 选项命名的目录中搜索标头,然后在通常的位置进行搜索。

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

【讨论】:

    【解决方案3】:

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

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

    相比之下(16.2 [cpp.include]/3),#include "..."

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

    因此,位置和技术完全由实现定义,除非在初始搜索中找不到源文件,#include "..." 会退回到 #include <...>

    措辞上的差异很重要:#include <...> 是否需要源文件;它完全取决于实现它如何处理标准头文件。用户编写的头文件应该使用#include "..." 拉入,因为这是处理源文件所必需的。

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

    【讨论】:

      猜你喜欢
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 2016-12-10
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      相关资源
      最近更新 更多