在C和C ++编程语言中,使用尖括号和使用引号之间的区别是什么 include
声明如下?
#include <filename>
#include "filename"
在C和C ++编程语言中,使用尖括号和使用引号之间的区别是什么 include
声明如下?
#include <filename>
#include "filename"
实际上,区别在于预处理器搜索包含文件的位置。
对于 #include <filename>
预处理器以依赖于实现的方式搜索,通常在编译器/ IDE预先指定的搜索目录中。此方法通常用于包括标准库头文件。
对于 #include "filename"
预处理器首先在与包含该指令的文件相同的目录中进行搜索,然后按照用于该指令的搜索路径进行搜索 #include <filename>
形成。此方法通常用于包括程序员定义的头文件。
GCC提供了更完整的描述 搜索路径上的文档。
唯一的方法是阅读您的实现文档。
在 C标准,第6.10.2节,第2至4段规定:
表单的预处理指令
#include <h-char-sequence> new-line
搜索一系列实现定义的位置,以查找由指定序列之间唯一标识的标头
<
和>
分隔符,并导致该标题的整个内容替换该指令。如何指定位置或标识的标头是实现定义的。表单的预处理指令
#include "q-char-sequence" new-line
导致由指定序列之间标识的源文件的全部内容替换该指令
"
分隔符。以实现定义的方式搜索指定的源文件。如果不支持此搜索,或者搜索失败,则会重新处理该指令,就像它读取一样#include <h-char-sequence> new-line
具有相同的包含序列(包括
>
来自原文的字符(如果有的话) 指示。表单的预处理指令
#include pp-tokens new-line
(允许与前两种形式中的一种不匹配)。之后的预处理令牌
include
在指令中处理就像在普通文本中一样。 (当前定义为宏名称的每个标识符将替换为其预处理标记的替换列表。)所有替换后生成的指令应与前两个表单中的一个匹配。一种预处理令牌序列的方法<
和a>
预处理令牌对或一对"
字符组合成单个标题名称预处理标记是实现定义的。定义:
h-char:除了换行符之外的源字符集的任何成员
>
q-char:源字符集的任何成员,除了换行符和
"
<和>之间的字符序列唯一地引用标题,该标题不一定是文件。实现几乎可以随意使用字符序列。 (但是,大多数情况下,只需将其视为文件名并在中进行搜索 包括路径,正如其他帖子所述。)
如果 #include "file"
如果支持,则实现首先查找给定名称的文件。如果不是(支持),或者如果搜索失败,则实现的行为就像另一个(#include <file>
)形式被使用。
此外,存在第三种形式,并在使用时使用 #include
指令与上述任何一种形式都不匹配。在这种形式中,一些基本的预处理(如宏扩展)是在“操作数”上完成的 #include
指令,结果预计与其他两种形式中的一种相匹配。
这里的一些好的答案引用了C标准,但忘记了POSIX标准,特别是该标准的具体行为 c99(例如C编译器) 命令。
根据 公开集团基本规格问题7,
-一世 目录
更改搜索名称不是绝对路径名的标头的算法,以查找由其命名的目录 目录 在通常的地方看之前的路径名。因此,名称以双引号(“”)括起来的标题应首先在文件的目录中搜索 #包括 行,然后在名为的目录中 -一世 选项,并在通常的地方持续。对于名称用尖括号(“<>”)括起来的标题,只能在名为的目录中搜索标题 -一世 选项,然后在通常的地方。目录命名为 -一世 应按指定的顺序搜索选项。实现应在单个中支持至少十个此选项的实例 C99 命令调用。
因此,在符合POSIX标准的环境中,使用符合POSIX标准的C编译器, #include "file.h"
可能会搜索 ./file.h
首先,在哪里 .
是带有文件的目录 #include
声明,而 #include <file.h>
,很可能会去搜索 /usr/include/file.h
首先,在哪里 /usr/include
是你的系统定义 平常的地方 对于标题(它似乎没有被POSIX定义)。
它确实:
"mypath/myfile" is short for ./mypath/myfile
同 .
是文件的目录所在的文件 #include
包含在和/或编译器的当前工作目录中,和/或 default_include_paths
和
<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile
如果 ./
在... <default_include_paths>
那么它没有什么区别。
如果 mypath/myfile
在另一个包含目录中,行为未定义。
GCC文件说 以下是关于两者的区别:
使用预处理指令包含用户和系统头文件
‘#include’
。它有两个变种:
#include <file>
此变体用于系统头文件。它在标准的系统目录列表中搜索名为file的文件。您可以使用以下目录将目录添加到此列表中
-I
选项(见 调用)。
#include "file"
此变体用于您自己的程序的头文件。它首先在包含当前文件的目录中搜索名为file的文件,然后在quote目录中搜索,然后使用相同的目录
<file>
。您可以使用以下命令将目录添加到引用目录列表中-iquote
选项。 的论点‘#include’
无论是用引号还是尖括号分隔,行为都像字符串常量,因为无法识别注释,并且不会扩展宏名称。从而,#include <x/*y>
指定包含名为的系统头文件x/*y
。但是,如果文件中出现反斜杠,则它们被视为普通文本字符,而不是转义字符。没有处理适合C中字符串常量的字符转义序列。从而,
#include "x\n\\y"
指定包含三个反斜杠的文件名。 (有些系统将'\'解释为路径名分隔符。所有这些都解释了‘/’
一样的方法。它最便于使用‘/’
。)如果文件名后面的行上有任何内容(注释除外),则会出错。
该 <file>
include告诉预处理器搜索 -I
目录和预定义目录 第一,然后在.c文件的目录中。该 "file"
include告诉预处理器搜索源文件的目录 第一,然后恢复 -I
和预定义的。无论如何都要搜索所有目的地,只有搜索顺序不同。
2011标准主要讨论“16.2源文件包含”中的包含文件。
2表单的预处理指令
# include <h-char-sequence> new-line
搜索一系列实现定义的位置,以查找由唯一标识的标头 <和>分隔符之间的指定序列,并导致 用标题的全部内容替换该指令。 如何指定地点或标识的标题是 实现定义。
3表单的预处理指令
# include "q-char-sequence" new-line
导致由该标识的源文件的全部内容替换该指令 “分隔符”之间的指定序列。命名的源文件是 以实现定义的方式搜索。如果这个搜索是 不支持,或者如果搜索失败,则将指令重新处理为 如果它读
# include <h-char-sequence> new-line
使用原始指令中相同的包含序列(包括>字符,如果有的话)。
注意 "xxx"
形式降级为 <xxx>
如果找不到文件,请填写表单。其余的是实现定义的。
按标准 - 是的,它们是不同的:
表单的预处理指令
#include <h-char-sequence> new-line
搜索一系列实现定义的位置,以查找由指定序列之间唯一标识的标头
<
和>
分隔符,并导致该标题的整个内容替换该指令。如何指定位置或标识的标头是实现定义的。表单的预处理指令
#include "q-char-sequence" new-line
导致由指定序列之间标识的源文件的全部内容替换该指令
"
分隔符。以实现定义的方式搜索指定的源文件。如果不支持此搜索,或者搜索失败,则会重新处理该指令,就像它读取一样#include <h-char-sequence> new-line
具有相同的包含序列(包括
>
来自原文的字符(如果有的话) 指示。表单的预处理指令
#include pp-tokens new-line
(允许与前两种形式中的一种不匹配)。之后的预处理令牌
include
在指令中处理就像在普通文本中一样。 (当前定义为宏名称的每个标识符将替换为其预处理标记的替换列表。)所有替换后生成的指令应与前两个表单中的一个匹配。一种预处理令牌序列的方法<
和a>
预处理令牌对或一对"
字符组合成单个标题名称预处理标记是实现定义的。定义:
h-char:除了换行符之外的源字符集的任何成员
>
q-char:源字符集的任何成员,除了换行符和
"
请注意,该标准没有说明实现定义方式之间的任何关系。第一种形式以一种实现定义的方式搜索,另一种以(可能是其他)实现定义的方式搜索。该标准还规定应存在某些包含文件(例如, <stdio.h>
)。
正式地,您必须阅读编译器的手册,但通常(按传统) #include "..."
form搜索文件的目录 #include
先发现,然后是目录 #include <...>
表单搜索(包含路径,例如系统标题)。
谢谢你的回答,特别是。 Adam Stelmaszczyk和piCookie,以及aib。
像许多程序员一样,我使用了非正式的使用方法 "myApp.hpp"
应用程序特定文件的表单,以及 <libHeader.hpp>
库和编译器系统文件的表单,即。中指定的文件 /I
和 INCLUDE
环境变量,多年来一直认为是标准。
但是,C标准规定搜索顺序是特定于实现的,这会使可移植性变得复杂。更糟糕的是,我们使用jam,它可以自动计算包含文件的位置。您可以为包含文件使用相对路径或绝对路径。即
#include "../../MyProgDir/SourceDir1/someFile.hpp"
较旧版本的MSVS需要双反斜杠(\\),但现在不需要。我不知道它什么时候改变了。只需使用正斜杠与'nix兼容(Windows会接受)。
如果你是 真 担心,使用 "./myHeader.h"
对于与源代码在同一目录中的包含文件(我当前的非常大的项目有一些重复的包含文件名分散 - 实际上是一个配置管理问题)。
这是 MSDN解释 复制到这里为了您的方便)。
引用形式
预处理器按以下顺序搜索包含文件:
- 与包含#include语句的文件位于同一目录中。
- 在当前打开的包含文件的目录中,按相反的顺序排列
他们被打开了。搜索从父包含文件的目录开始
继续向上通过任何祖父母包含文件的目录。- 沿着每个人指定的路径
/I
编译选项。- 沿着由路径指定的路径
INCLUDE
环境变量。角括号形式
预处理器按以下顺序搜索包含文件:
- 沿着每个人指定的路径
/I
编译选项。- 在命令行上进行编译时,沿着由...指定的路径进行编译
INCLUDE
环境变量。
至少对于GCC版本<= 3.0,角括号形式不会在包含文件和包含文件之间产生依赖关系。
因此,如果要生成依赖性规则(使用GCC -M选项作为示例),则必须使用引用的表单来存储应该包含在依赖关系树中的文件。