在C和C ++编程语言中,使用尖括号和在include
语句中使用引号有什么区别,如下所示?
#include <filename>
#include "filename"
答案 0 :(得分:1216)
实际上,区别在于预处理器搜索包含文件的位置。
对于#include <filename>
,预处理器以依赖于实现的方式搜索,通常在编译器/ IDE预先指定的搜索目录中搜索。此方法通常用于包含标准库头文件。
对于#include "filename"
,预处理器首先在与包含该指令的文件相同的目录中进行搜索,然后按照用于#include <filename>
表单的搜索路径进行搜索。此方法通常用于包含程序员定义的头文件。
GCC documentation on search paths中提供了更完整的说明。
答案 1 :(得分:645)
了解的唯一方法是阅读实施文档。
在the C standard第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
之后的预处理标记的处理方式与普通文本一样。 (当前定义为宏名称的每个标识符将替换为其预处理标记的替换列表。)所有替换后生成的指令应与前两个表单中的一个匹配。将<
和>
预处理标记对或一对"
字符之间的预处理标记序列组合成单个标题名称预处理标记的方法是实现定义的。解释
- 之外的任何成员
h-char:源字符集中除换行符和
>
- 之外的任何成员
q-char:源字符集中除换行符和
"
答案 2 :(得分:249)
&lt;之间的字符序列。和&gt;唯一引用标题,不一定是文件。实现几乎可以随意使用字符序列。 (但是,大多数情况下,只需将其视为文件名并在包含路径中进行搜索,就像其他帖子所述。)
如果使用#include "file"
表单,则实现首先查找给定名称的文件(如果支持)。如果不是(支持),或者搜索失败,则实现的行为就像使用了另一个(#include <file>
)表单一样。
此外,存在第三种形式,当#include
指令与上述任何一种形式都不匹配时使用。在这种形式中,一些基本的预处理(例如宏扩展)是在#include
指令的“操作数”上完成的,结果应该与其他两种形式中的一种匹配。
答案 3 :(得分:100)
这里的一些好答案引用了C标准,但忘记了POSIX标准,尤其是c99 (e.g. C compiler)命令的特定行为。
根据The Open Group Base Specifications Issue 7,
-I 目录
在查看常用位置之前,更改搜索名称不是绝对路径名的标头的算法,以查找目录路径名所指定的目录。因此,名称用双引号(“”)括起来的标题应首先在 #include 行的文件目录中搜索,然后在 -I <中指定的目录中搜索/ strong>选项,最后在通常的地方。对于名称用尖括号(“&lt;&gt;”)括起来的标题,只能在 -I 选项中指定的目录中搜索标题,然后在通常的位置搜索标题。在 -I 选项中命名的目录应按指定的顺序进行搜索。实现应在单个 c99 命令调用中支持至少十个此选项的实例。
因此,在POSIX兼容环境中,使用符合POSIX标准的C编译器,#include "file.h"
可能首先搜索./file.h
,其中.
是文件所在的目录#include
语句虽然#include <file.h>
可能会首先搜索/usr/include/file.h
,其中/usr/include
是您系统定义的常用地点的标题(似乎没有POSIX定义。
答案 4 :(得分:41)
GCC documentation says关于两者之间的区别如下:
使用预处理指令
‘#include’
包含用户和系统头文件。它有两种变体:<强>
#include <file>
强>此变体用于系统头文件。它在标准的系统目录列表中搜索名为file的文件。您可以使用
-I
选项将目录添加到此列表中(请参阅Invocation)。<强>
#include "file"
强>此变体用于您自己程序的头文件。它首先在包含当前文件的目录中搜索名为file的文件,然后在quote目录中搜索,然后搜索用于
<file>
的相同目录。您可以使用-iquote
选项将目录添加到引用目录列表中。‘#include’
的参数,无论是用引号还是尖括号分隔,都表现为字符串常量,因为注释无法识别,宏名称不会扩展。因此,#include <x/*y>
指定包含名为x/*y
的系统头文件。但是,如果文件中出现反斜杠,则它们被视为普通文本字符,而不是转义字符。没有处理适合C中字符串常量的字符转义序列。因此,
#include "x\n\\y"
指定包含三个反斜杠的文件名。 (有些系统将'\'解释为路径名分隔符。所有这些都以同样的方式解释‘/’
。仅使用‘/’
是最便携的。)如果文件名后的行上有任何内容(注释除外),则会出错。
答案 5 :(得分:40)
它确实:
"mypath/myfile" is short for ./mypath/myfile
.
是包含#include
的文件的目录,和/或编译器的当前工作目录,和/或default_include_paths
和
<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile
如果./
位于<default_include_paths>
,那么它就无法发挥作用。
如果mypath/myfile
位于另一个包含目录中,则行为未定义。
答案 6 :(得分:30)
<file>
include告诉预处理器在-I
目录和预定义目录 first 中搜索,然后在.c文件的目录中搜索。 "file"
include告诉预处理器搜索源文件的目录 first ,然后恢复为-I
并预定义。无论如何都会搜索所有目的地,只有搜索顺序不同。
2011标准主要讨论“16.2源文件包含”中的包含文件。
2
形式的预处理指令
# include <h-char-sequence> new-line
在一系列实现定义的位置搜索由唯一标识的标头 &之间的指定顺序和&gt;分隔符,并导致 用标题的全部内容替换该指令。 如何指定地点或标识的标题是 实现定义的。
3表格
的预处理指令
# include "q-char-sequence" new-line
导致由该标识的源文件的全部内容替换该指令 “分隔符”之间的指定序列。命名的源文件是 以实现定义的方式搜索。如果这个搜索是 不受支持,或者如果搜索失败,则将指令重新处理为 如果它读了
# include <h-char-sequence> new-line
使用原始指令中相同的包含序列(包括>字符,如果有的话)。
请注意,如果找不到该文件,"xxx"
形式会降级为<xxx>
格式。其余的是实现定义。
答案 7 :(得分:18)
按照标准 - 是的,它们是不同的:
表单
的预处理指令#include <h-char-sequence> new-line
在一系列实现定义的位置中搜索由
<
和>
分隔符之间的指定序列唯一标识的标头,并导致该标头的整个内容替换该指令。如何指定场所或标识的标题是实现定义的。表单
的预处理指令#include "q-char-sequence" new-line
导致由
一样"
分隔符之间的指定序列标识的源文件的全部内容替换该伪指令。以实现定义的方式搜索指定的源文件。如果不支持此搜索,或者搜索失败,则会重新处理该指令,就好像它已读取#include <h-char-sequence> new-line
使用相同的包含序列(包括
>
个字符,如果有的话)来自原始序列 指令。表单
的预处理指令允许使用#include pp-tokens new-line
(与前两种形式中的一种不匹配)。指令中
include
之后的预处理标记的处理方式与普通文本一样。 (当前定义为宏名称的每个标识符将替换为其预处理标记的替换列表。)所有替换后生成的指令应与前两个表单中的一个匹配。将<
和>
预处理标记对或一对"
字符之间的预处理标记序列组合成单个标题名称预处理标记的方法是实现定义的。解释
- 之外的任何成员
h-char:源字符集中除换行符和
>
- 之外的任何成员
q-char:源字符集中除换行符和
"
请注意,该标准并未说明实现定义方式之间的任何关系。第一种形式以一种实现定义的方式搜索,另一种以(可能是其他)实现定义的方式搜索。该标准还规定应存在某些包含文件(例如,<stdio.h>
)。
正式地,您必须阅读编译器的手册,但通常(按传统),#include "..."
表单会搜索首先找到#include
的文件的目录,并且然后是#include <...>
表单搜索的目录(包含路径,例如系统头)。
答案 8 :(得分:15)
感谢您的回答,尤其是Adam Stelmaszczyk和piCookie,以及aib。
与许多程序员一样,我使用了将"myApp.hpp"
表单用于特定于应用程序的文件的非正式约定,以及用于库和编译器系统文件的<libHeader.hpp>
表单,即{{1}中指定的文件和/I
环境变量,多年来一直认为这是标准。
但是,C标准规定搜索顺序是特定于实现的,这会使可移植性变得复杂。更糟糕的是,我们使用jam,它可以自动计算包含文件的位置。您可以为包含文件使用相对路径或绝对路径。即。
INCLUDE
旧版本的MSVS需要双反斜杠(\\),但现在不需要。我不知道它什么时候改变了。只需使用正斜杠与'nix兼容(Windows会接受)。
如果您真的担心它,请使用#include "../../MyProgDir/SourceDir1/someFile.hpp"
将包含文件放在与源代码相同的目录中(我当前的非常大的项目有一些重复的包含文件名分散关于 - 真的是一个配置管理问题。)
以下是为方便起见而复制的MSDN explanation。
引用表格
预处理器按此顺序搜索包含文件:
- 与包含#include语句的文件位于同一目录中。
- 在当前打开的包含文件的目录中,按照与之相反的顺序 他们被打开了。搜索从父包含文件的目录开始,然后是 继续向上通过任何祖父母包含文件的目录。
- 沿着每个
"./myHeader.h"
编译器选项指定的路径。- 沿着
醇>/I
环境变量指定的路径。角括号表格
预处理器按此顺序搜索包含文件:
- 沿着每个
INCLUDE
编译器选项指定的路径。- 在命令行上进行编译时,沿着
醇>/I
环境变量指定的路径进行编译。
答案 9 :(得分:13)
至少对于GCC版本&lt; = 3.0,角括号形式不会在包含文件和包含文件之间产生依赖关系。
因此,如果要生成依赖关系规则(使用GCC -M选项作为例子),则必须使用引用的表单来存储应该包含在依赖关系树中的文件。
答案 10 :(得分:12)
当您使用#include&lt; filename&gt;时,预处理器在C \ C ++头文件(stdio.h \ cstdio,string,vector等)的目录中查找文件。但是,当你使用#include“filename”时:首先,预处理器在当前目录中查找文件,如果它不在这里 - 他在C \ C ++头文件目录中查找它。
答案 11 :(得分:12)
#include <file.h>
告诉编译器在其“包含”目录中搜索标题,例如对于MinGW,编译器将在C:\ MinGW \ include \或编译器安装的任何位置搜索file.h
。
#include "file"
告诉编译器搜索file
的当前目录(即源文件所在的目录)。
您可以使用GCC的-I
标志告诉它,当它遇到包含斜角括号的包含时,它还应该在-I
之后搜索目录中的标题。 GCC会将标记后的目录视为includes
目录。
例如,如果您在自己的目录中有一个名为myheader.h
的文件,如果您使用标记#include <myheader.h>
调用GCC,则可以说-I .
(表示它应该搜索包含在当前目录中。)
如果没有-I
标记,则必须使用#include "myheader.h"
来包含该文件,或将myheader.h
移动到编译的include
目录中。
答案 12 :(得分:12)
对于#include ""
,编译器通常会搜索包含该文件夹的文件夹,然后搜索其他文件夹。对于#include <>
,编译器不会搜索当前文件的文件夹。
答案 13 :(得分:10)
#include <>
适用于预定义的标头文件 如果头文件是预定义的,那么你只需在尖括号中编写头文件名,它就像这样(假设我们有一个预定义的头文件名iostream):
#include <iostream>
#include " "
适用于程序员定义的头文件 如果您(程序员)编写了自己的头文件,那么您可以在引号中编写头文件名。因此,假设您编写了一个名为myfile.h
的头文件,那么这是一个如何使用include伪指令来包含该文件的示例:
#include "myfile.h"
答案 14 :(得分:9)
带有尖括号的#include将搜索要包含的文件的“依赖于实现的位置列表”(这是一种非常复杂的说“系统标题”的方式)。
带引号的#include将只搜索文件(并且,“以依赖于实现的方式”,bleh)。这意味着,在普通英语中,它将尝试应用您抛出的路径/文件名,并且不会在系统路径前添加或以其他方式篡改。
此外,如果#include“”失败,则会将其重新读为#include&lt;&gt;按标准。
gcc documentation有一个(编译器特定的)描述虽然特定于gcc而不是标准,但比ISO标准的律师风格的讨论要容易理解。
答案 15 :(得分:8)
这里的许多答案都集中在编译器为了查找文件而搜索的路径上。虽然这是大多数编译器所做的,但是允许符合标准的编译器使用标准头的效果进行预编程,并将#include <list>
视为一个开关,它根本不需要作为文件存在。
这不是纯粹的假设。至少有一个编译器以这种方式工作。建议仅在标准标题中使用#include <xxx>
。
答案 16 :(得分:8)
#include "filename" // User defined header
#include <filename> // Standard library header.
示例:
此处的文件名是Seller.h
:
#ifndef SELLER_H // Header guard
#define SELLER_H // Header guard
#include <string>
#include <iostream>
#include <iomanip>
class Seller
{
private:
char name[31];
double sales_total;
public:
Seller();
Seller(char[], double);
char*getName();
#endif
在类实现中(例如,Seller.cpp
和其他将使用文件Seller.h
的文件),现在应该包含用户定义的标头,如下所示:
#include "Seller.h"
答案 17 :(得分:8)
#include <abc.h>
用于包含标准库文件。因此,编译器将检查标准库头文件所在的位置。
#include "xyz.h"
将告诉编译器包含用户定义的头文件。因此,编译器将检查当前文件夹中的这些头文件或-I
已定义的文件夹。
答案 18 :(得分:6)
在C ++中,以两种方式包含文件:
第一个是#include,它告诉预处理器在预定义的默认位置查找文件。 此位置通常是INCLUDE环境变量,表示包含文件的路径。
第二种类型是#include“filename”,它告诉预处理器首先在当前目录中查找文件,然后在用户设置的预定义位置查找它。
答案 19 :(得分:6)
“&lt; filename&gt;”在标准C库位置搜索
而“filename”也在当前目录中搜索。
理想情况下,您可以使用&lt; ...&gt;标准C库和“...”用于您编写并存在于当前目录中的库。
答案 20 :(得分:5)
引用系统文件时使用#include <filename>
。这是一个头文件,可以在/usr/include
或/usr/local/include
等系统默认位置找到。对于需要包含在另一个程序中的自己的文件,您必须使用#include "filename"
语法。
答案 21 :(得分:4)
简单的一般规则是使用有角度的括号来包含编译器附带的头文件。使用双引号包含任何其他头文件。大多数编译器都是这样做的。
1.9 — Header files 更详细地解释了预处理器指令。如果您是新手程序员,该页面应该可以帮助您理解所有这些。我是从这里学到的,我一直在工作。
答案 22 :(得分:3)
#include <filename>
当您要使用C / C ++系统或编译器库的头文件时,使用。这些库可以是stdio.h,string.h,math.h等。
#include "path-to-file/filename"
如果要使用项目文件夹或其他位置的自定义头文件,则使用。
有关预处理程序和标头的更多信息。阅读 C - Preprocessors 。
答案 23 :(得分:2)
首先,在调用伪指令的当前目录中查找头文件的存在。如果找不到,它将在标准系统目录的预配置列表中搜索。
这将在调用伪指令的当前目录中查找头文件的存在。
确切的搜索目录列表取决于目标系统,GCC的配置方式以及安装位置。 您可以通过-v选项运行GCC编译器的搜索目录列表。
您可以使用-I dir 将其他目录添加到搜索路径,这将导致在当前目录之后(对于指令的引号形式)并在标准系统之前搜索dir。目录。
基本上,形式“ xxx”不过是在当前目录中搜索;如果没有找到表格
答案 24 :(得分:1)
"" 将首先搜索 ./。然后搜索默认的包含路径。 你可以使用这样的命令来打印默认的包含路径:
gcc -v -o a a.c
这里有一些例子让事情更清楚: 代码 a.c 有效
// a.c
#include "stdio.h"
int main() {
int a = 3;
printf("a = %d\n", a);
return 0;
}
b.c 的代码也可以
\\ b.c
#include <stdio.h>
int main() {
int a = 3;
printf("a = %d\n", a);
return 0;
}
但是当我在当前目录中创建一个名为 stdio.h 的新文件时
// stdio.h
inline int foo()
{
return 10;
}
a.c 会产生编译错误,但 b.c 仍然有效
和 "", <> 可以与相同的文件名一起使用。因为搜索路径优先级不同。 所以直流也有效
// d.c
#include <stdio.h>
#include "stdio.h"
int main()
{
int a = 0;
a = foo();
printf("a=%d\n", a);
return 0;
}
~
答案 25 :(得分:1)
#include <file>
包含文件的默认包含目录。
#include "file"
在当前文件的编译目录中包含一个文件。
答案 26 :(得分:1)
要基于当前配置,使用gcc查看系统上的搜索顺序,可以执行以下命令。您可以找到有关此命令here
的更多详细信息 cpp -v /dev/null -o /dev/null
Apple LLVM版本10.0.0(clang-1000.10.44.2)
目标:x86_64-apple-darwin18.0.0
线程模型:posix InstalledDir:库/开发人员/ CommandLineTools / usr / bin
“ /库/开发人员/ CommandLineTools / usr / bin / clang” -cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror =不推荐使用-objc-isa-usage -E -disable-free -disable-llvm-verifier -discard-value-names -main-file-name null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-cpu penryn -dwarf-columninfo -debugger-tuning = lldb -target-linker-version 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 -isysroot /图书馆/开发人员/CommandLineTools/SDKs/MacOSX10.14.sdk -I / usr / local / include -fdebug-compilation-dir / Users / hogstrom -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime = macosx- 10.14.0 -fmax-type-align = 16 -fdiagnostics-show-option -fcolor-diagnostics -traditional-cpp -o--xc / dev / null
clang -cc1版本10.0.0(clang-1000.10.44.2)默认目标x86_64-apple-darwin18.0.0忽略 不存在的目录“ /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include” 忽略不存在的目录“ /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks”
#include“ ...”搜索从此处开始:
#include <...>搜索从此处开始:
/ usr / local / include
/Library/Developer/CommandLineTools/usr/lib/clang/10.0.0/include
/ Library / Developer / CommandLineTools / usr / include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks (框架目录)
搜索列表结尾。
答案 27 :(得分:1)
编译器生成的实现定义的警告可以(并且将会)以不同于程序库的方式对待系统库。
所以
#include <myFilename>
——它实际上声明了 myFilename 位于系统库位置——很可能(并且可能会)隐藏死代码和未使用的变量警告等,这些会在您使用时显示:
#include "myFilename"
答案 28 :(得分:0)
#include <filename> (1)
#include "filename" (2)
#include
包括由文件名标识的源文件到紧跟在指令之后的行的当前源文件中。
该指令的第一个版本仅搜索标准包含 目录。标准C ++库,以及标准C库, 隐式包含在标准包含目录中。标准 包含目录可以由用户通过编译器控制 选项。
第二个版本首先搜索当前文件所在的目录 驻留,并且只有在找不到文件时才搜索标准 包括目录。
如果找不到文件,程序就会格式不正确。
答案 29 :(得分:0)
有两种写#include语句的方法,它们是:
#include"filename"
#include<filename>
每种形式的含义是
#include"mylib.h"
此命令将在可能已设置的包含搜索路径中查找当前目录中的文件mylib.h
以及指定的目录列表。
#include<mylib.h>
此命令将仅在指定的目录列表中查找文件mylib.h
。
include搜索路径只不过是要搜索要包含的文件的目录列表。不同的C编译器允许您以不同的方式设置搜索路径。
答案 30 :(得分:0)
#include <filename>
#include "filename"
#include <filename>
,并在系统头文件存储的位置搜索该头文件。#include <filename>
花费更多的编译时间。答案 31 :(得分:0)
通常,区别在于预处理器在其中搜索头文件:
#include是预处理程序指令,用于包含头文件。这两个#include都用于在程序中添加或包括头文件,但首先是包括系统头文件,然后是用于用户定义的头文件。
检查gcc文档gcc include files
答案 32 :(得分:-1)
#include <filename>
将从C ++库中找到相应的文件。
这意味着如果你在C ++库文件夹中有一个名为hello.h的文件,#include <hello.h>
将加载它。
但是,
#include "filename"
将在源文件所在的同一目录中找到该文件。
此外,
#include "path_to_file/filename"
将在您在path_to_file
中输入的目录中找到该文件。
答案 33 :(得分:-1)
我相信包含在双引号中的标题将在相同的系统路径中查找,如果在当前目录中找不到它们,则会包含angle-bracketed包含。
答案 34 :(得分:-2)
要包含预定义的库头文件,请使用#include<filename>
,而要包含用户定义的头文件,#include "filename"
是相关的。
答案 35 :(得分:-2)
搜索头文件的顺序不同。 &LT; XXX.h&GT;首先搜索标准头文件,而“XXX.h”首先搜索工作区的头文件。