最近I learned gnu cpp和msvc cl对#include
个文件的处理方式不同。常见的行为是查看includ_ing_文件旁边的目录,然后遍历include路径(显然使用-I
或/I
编译器参数进行设置。)
但现在我想知道:我是否正确学习,或者实际上是否还有预处理器的标准?
答案 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 "..."
指令在顶级源文件中。两者都是有效的,并且这两种方法都存在争议,尽管我个人觉得搜索标题更直观,更易于使用的目录。