在include指令中使用尖括号和引号有什么区别?

#包括<文件名>#包括“文件名”


当前回答

带有尖括号的#include将搜索“依赖于实现的位置列表”(这是一种非常复杂的方式来表示“系统头”)以查找要包含的文件。

带引号的#include将只搜索文件(并且,“以依赖于实现的方式”,bleh)。这意味着,在正常的英语中,它将尝试应用你扔给它的路径/文件名,而不会预先设置系统路径或篡改它。

此外,如果#include“”失败,则标准会将其重新读取为#include<>。

gcc文档有一个(特定于编译器的)描述,虽然它是特定于gcc而非标准的,但它比ISO标准的律师式描述更容易理解。

其他回答

感谢您的回答,特别是Adam Stelmaszczyk和piCookie,以及aib。

与许多程序员一样,多年来,我一直使用“myApp.hpp”格式作为应用程序特定文件,使用<libHeader.hpp>格式作为库和编译器系统文件(即/I和INCLUDE环境变量中指定的文件)的非正式约定,认为这是标准。

然而,C标准规定搜索顺序是特定于实现的,这会使可移植性变得复杂。更糟糕的是,我们使用了jam,它可以自动找出包含文件的位置。可以为包含文件使用相对路径或绝对路径。即

#include "../../MyProgDir/SourceDir1/someFile.hpp"

旧版本的MSVS需要双反斜杠(\\),但现在不需要了。我不知道什么时候变了。为了与'nix兼容,只需使用正斜杠(Windows将接受这一点)。

如果您真的担心这个问题,请使用“./myHeader.h”作为源代码所在目录中的包含文件(我当前的大型项目中有一些重复的包含文件名--这确实是一个配置管理问题)。

为了方便起见,这里复制了MSDN说明)。

引用的表单预处理器按以下顺序搜索包含文件:在与包含#include语句的文件相同的目录中。在当前打开的include文件的目录中,按以下相反顺序他们被打开了。搜索从父包含文件的目录开始继续向上通过任何祖父母包含文件的目录。沿着每个/I编译器选项指定的路径。沿着INCLUDE环境变量指定的路径。角钢支架形式预处理器按以下顺序搜索包含文件:沿着每个/I编译器选项指定的路径。在命令行上进行编译时,沿着INCLUDE环境变量指定的路径进行编译。

表格1-#include<xxx>

首先,在调用指令的当前目录中查找头文件的存在。如果未找到,则在预配置的标准系统目录列表中进行搜索。

表格2-#包括“xxx”

这将查找在调用指令的当前目录中是否存在头文件。


确切的搜索目录列表取决于目标系统、GCC的配置方式以及安装位置。通过使用-v选项运行GCC编译器,可以找到GCC编译器的搜索目录列表。

您可以使用-Idir将其他目录添加到搜索路径中,这会导致在当前目录之后(对于指令的引号形式)和标准系统目录之前搜索dir。


基本上,表单“xxx”只是在当前目录中搜索;如果未找到,则返回表单

#include<>用于预定义的头文件

如果头文件是预定义的,那么您只需将头文件名写在尖括号中,它看起来像这样(假设我们有一个预定义的头文件名iostream):

#include <iostream>

#include“”表示程序员定义的头文件

如果你(程序员)编写了自己的头文件,那么你会将头文件名用引号括起来。因此,假设您编写了一个名为myfile.h的头文件,那么这是如何使用include指令包含该文件的示例:

#include "myfile.h"

按照标准-是的,它们是不同的:

表单的预处理指令#包含<h-char-sequence>新行在实现定义的位置序列中搜索由<和>分隔符之间的指定序列唯一标识的头,并用头的全部内容替换该指令。如何指定位置或标识标题是实现定义的。表单的预处理指令#包括“q-char-sequence”新行导致用“分隔符”之间的指定序列标识的源文件的全部内容替换该指令。将以实现定义的方式搜索命名的源文件。如果不支持此搜索,或者搜索失败,则会像读取指令一样重新处理该指令#包含<h-char-sequence>新行具有与原始文件相同的包含序列(包括>个字符,如果有)指令。表单的预处理指令#包含pp令牌新行(与前两种形式之一不匹配)。指令中include之后的预处理标记与普通文本中的处理相同。(当前定义为宏名称的每个标识符由其预处理令牌的替换列表替换。)所有替换后产生的指令应与前两种形式之一匹配。实现定义了一种方法,通过该方法,<和>预处理令牌对或一对“字符”之间的一系列预处理令牌组合成单个标头名称预处理令牌。定义:h-char:源字符集的任何成员,除了换行符和>q-char:源字符集的任何成员,除了换行符和“

注意,标准没有说明实现定义的方式之间的任何关系。第一个表单以一种实现定义的方式进行搜索,另一个表单以(可能是其他)实现定义的方法进行搜索。该标准还规定应存在某些包含文件(例如,<stdio.h>)。

从形式上讲,您必须阅读编译器的手册,但通常(按照传统)#include“…”表单会搜索首先找到#include的文件目录,然后搜索#include<…>的目录表单搜索(包括路径,例如系统标题)。

这里的一些好答案引用了C标准,但忘记了POSIX标准,特别是c99(例如C编译器)命令的特定行为。

根据开放组基础规范第7版,

-I目录更改搜索名称不是绝对路径名的标头的算法,以便在查找通常位置之前先查找由目录路径名命名的目录。因此,名称用双引号(“”)括起来的头应首先在文件的目录中搜索#include行,然后在-I选项中命名的目录中,最后在通常的位置搜索。对于名称用尖括号(“<>”)括起来的标题,只能在-I选项中命名的目录中搜索标题,然后在通常的位置搜索标题。应按照指定的顺序搜索-I选项中命名的目录。实现应在单个c99命令调用中支持至少十个此选项的实例。

因此,在符合POSIX的环境中,使用符合POSIX标准的C编译器,#include“file.h”可能会被搜索/首先是文件.h,其中。是包含#include语句的文件所在的目录,而#include<file.h>可能会首先搜索/usr/include/file.h,其中/usr/include是系统定义的头的常用位置(POSIX似乎没有定义)。