在C和C编程语言中,使用尖括号和在 include 语句中使用引号有什么区别,如下所示?
include
#include <filename>
#include "filename"
当您使用#include <filename>时,预处理器在C \ C头文件(stdio.h \ cstdio,string,vector等)的目录中查找文件 . 但是,当你使用#include“filename”时:首先,预处理器在当前目录中查找文件,如果它不在这里 - 他在C \ C头文件目录中查找它 .
在C中,以两种方式包含文件:
第一个是#include,它告诉预处理器在预定义的默认位置查找文件 . 此位置通常是INCLUDE环境变量,表示包含文件的路径 .
第二种类型是#include“filename”,它告诉预处理器首先在当前目录中查找文件,然后在用户设置的预定义位置查找它 .
编写#include语句有两种方法 . 这些是:
#include"filename" #include<filename>
每种形式的含义是
#include"mylib.h"
此命令将查找当前目录中的文件 mylib.h 以及可能已设置的包含搜索路径中提到的指定目录列表 .
mylib.h
#include<mylib.h>
此命令仅在指定的目录列表中查找文件 mylib.h .
包含搜索路径只是一个目录列表,可以搜索包含的文件 . 不同的C编译器允许您以不同的方式设置搜索路径 .
简单的一般规则是使用有角度的括号来包含编译器附带的头文件 . 使用双引号包含任何其他头文件 . 大多数编译器都是这样做的 .
1.9 — Header files更详细地解释了预处理器指令 . 如果您是新手程序员,该页面应该可以帮助您理解所有这些 . 我是从这里学到的,我一直在工作 .
它确实:
"mypath/myfile" is short for ./mypath/myfile
. 是包含 #include 的文件的目录,和/或编译器的当前工作目录,和/或 default_include_paths
.
#include
default_include_paths
和
<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile
如果 ./ 在 <default_include_paths> 中,那么它没有什么区别 .
./
<default_include_paths>
如果 mypath/myfile 在另一个包含目录中,则行为未定义 .
mypath/myfile
GCC documentation says以下关于两者的区别:
使用预处理指令“#include”包含用户和系统头文件 . 它有两个变体:#include <file>此变体用于系统头文件 . 它在标准的系统目录列表中搜索名为file的文件 . 您可以使用-I选项将目录添加到此列表中(请参阅调用) . #include“file”此变体用于您自己程序的头文件 . 它首先在包含当前文件的目录中搜索名为file的文件,然后在quote目录中搜索,然后在<file>中搜索相同的目录 . 您可以使用-iquote选项将目录添加到引用目录列表中 . '#include'的参数,无论是用引号还是尖括号分隔,都表现为字符串常量,因为无法识别注释,并且不会扩展宏名称 . 因此,#include <x / * y>指定包含名为x / * y的系统头文件 . 但是,如果文件中出现反斜杠,则它们被视为普通文本字符,而不是转义字符 . 没有处理适合C中字符串常量的字符转义序列 . 因此,#include“x \ n \ y”指定包含三个反斜杠的文件名 . (有些系统将''解释为路径名分隔符 . 所有这些都以同样的方式解释'/' . 仅使用'/'是最便携的 . )如果有任何内容(除了注释)之外是一个错误文件名后面的行 .
谢谢你的回答,特别是 . Adam Stelmaszczyk和piCookie,以及aib .
像许多程序员一样,我使用了 "myApp.hpp" 表单用于应用程序特定文件的非正式约定,以及用于库和编译器系统文件的 <libHeader.hpp> 表单,即 /I 和 INCLUDE 环境变量中指定的文件,多年来一直认为这是标准 .
"myApp.hpp"
<libHeader.hpp>
/I
INCLUDE
但是,C标准规定搜索顺序是特定于实现的,这会使可移植性变得复杂 . 更糟糕的是,我们使用jam,它可以自动计算包含文件的位置 . 您可以为包含文件使用相对路径或绝对路径 . 即
#include "../../MyProgDir/SourceDir1/someFile.hpp"
较旧版本的MSVS需要双反斜杠(\),但现在不需要 . 我不知道它什么时候改变了 . 只需使用正斜杠与'nix兼容(Windows会接受) .
如果您真的很担心它,请将 "./myHeader.h" 用于与源代码位于同一目录中的包含文件(我当前的非常大的项目有一些重复的包含文件名分散 - 实际上是配置管理问题) .
"./myHeader.h"
这是为了您的方便而复制的MSDN explanation .
引用形式预处理器按以下顺序搜索包含文件:与包含#include语句的文件位于同一目录中 . 在当前打开的包含文件的目录中,按照打开它们的相反顺序 . 搜索从父包含文件的目录开始,并继续向上遍历任何祖父包含文件的目录 . 沿着每个/ I编译器选项指定的路径 . 沿着INCLUDE环境变量指定的路径 . Angle-bracket形式预处理器按以下顺序搜索包含文件:沿着每个/ I编译器选项指定的路径 . 编译时在命令行上,沿着INCLUDE环境变量指定的路径发生 .
按标准 - 是的,它们是不同的:
#include <h-char-sequence> new-line形式的预处理指令搜索一系列实现定义的位置,以查找由<和>分隔符之间的指定序列唯一标识的标头,并使标头的整个内容替换该指令 . 如何指定位置或标识的标头是实现定义的 . #include“q-char-sequence”换行符形式的预处理指令导致由“delimiters”之间指定序列标识的源文件的全部内容替换该指令 . 以实现定义的方式搜索指定的源文件 . 如果不支持此搜索,或者搜索失败,该指令被重新处理,就像它读取#include <h-char-sequence> new-line一样使用原始指令中相同的包含序列(包括>字符,如果有的话) . #include pp-tokens new-line形式的预处理指令(允许与前两种形式中的一种不匹配) . 指令中包含的预处理标记的处理方式与普通文本一样 . (当前定义为宏名称的每个标识符将替换为其预处理标记的替换列表 . )所有替换后生成的指令应与前两个表单中的一个匹配 . 将<和>预处理标记对或一对“字符”之间的预处理标记序列组合成单个 Headers 名称预处理标记的方法是实现定义的 . 定义:h-char:源字符的任何成员除了换行字符和> q-char之外的其他设置:除了换行符之外的源字符集的任何成员和“
请注意,该标准没有说明实现定义方式之间的任何关系 . 第一种形式以一种实现定义的方式搜索,另一种以(可能是其他)实现定义的方式搜索 . 该标准还规定应存在某些包含文件(例如, <stdio.h> ) .
<stdio.h>
在正式情况下,您必须阅读编译器的手册,但通常(按传统), #include "..." 表单会搜索首先找到 #include 的文件的目录,然后搜索 #include <...> 表单搜索的目录(包含路径,例如系统 Headers ) .
#include "..."
#include <...>
带有尖括号的#include将搜索要包含的文件的“依赖于实现的位置列表”(这是一种非常复杂的说“系统头”的方式) .
带引号的#include将只搜索文件(并且,“以依赖于实现的方式”,bleh) . 这意味着,在普通英语中,它将尝试应用您在其上投掷的路径/文件名,并且不会预先添加系统路径或以其他方式篡改它 .
此外,如果#include“”失败,则标准将其重新读为#include <> .
gcc documentation有一个(编译器特定的)描述虽然特定于gcc而不是标准,但比ISO标准的律师风格的讨论要容易理解 .
搜索头文件的顺序不同 . <XXX.h>首先搜索标准 Headers ,而“XXX.h”首先搜索工作区的 Headers 文件 .
将从C库中找到相应的文件 . 这意味着如果你在C库文件夹中有一个名为hello.h的文件, #include <hello.h> 将加载它 .
#include <hello.h>
但,
将在源文件所在的同一目录中找到该文件 .
此外,
#include "path_to_file/filename"
将在 path_to_file 中键入的目录中找到该文件 .
path_to_file
#include <abc.h>
用于包括标准库文件 . 因此,编译器将检查标准库头所在的位置 .
#include "xyz.h"
将告诉编译器包含用户定义的头文件 . 因此,编译器将检查当前文件夹或 -I 已定义文件夹中的这些头文件 .
-I
首先,从where指令查找当前目录中是否存在头文件被调用 . 如果未找到,则在预配置的标准系统目录列表中搜索 .
这将在调用where指令的当前目录中查找头文件的存在 .
确切的搜索目录列表取决于目标系统,GCC的配置方式以及安装位置 . 您可以通过使用-v选项运行GCC编译器的搜索目录列表 .
您可以使用 - Idir将其他目录添加到搜索路径,这会导致在当前目录(对于指令的引用形式)之后和标准系统目录之前搜索dir .
基本上,“xxx”形式只是在当前目录中搜索;如果没有找到退回形式
我相信包含在双引号中的 Headers 将在相同的系统路径中查找,如果在当前目录中找不到它们,则包括angle-bracketed .
这里的许多答案都集中在编译器为了找到文件而搜索的路径上 . 虽然这是大多数编译器所做的,但是允许符合标准的编译器使用标准头的效果进行预编程,并将 #include <list> 视为一个开关,它根本不需要作为文件存在 .
#include <list>
这不是纯粹的假设 . 至少有一个编译器以这种方式工作 . 建议仅使用标准 Headers #include <xxx> .
#include <xxx>
#include <file.h> 告诉编译器在其"includes"目录中搜索 Headers ,例如对于MinGW,编译器将在C:\ MinGW \ include \或安装编译器的任何地方搜索 file.h .
#include <file.h>
file.h
#include "file" 告诉编译器搜索 file 的当前目录(即源文件所在的目录) .
#include "file"
file
您可以使用GCC的 -I 标志告诉它,当遇到包含斜角括号的包含时,它还应该在 -I 之后搜索目录中的 Headers . GCC会将标志后的目录视为 includes 目录 .
includes
例如,如果您在自己的目录中有一个名为 myheader.h 的文件,如果您使用标志 -I . 调用GCC(表示它应该在当前目录中搜索包含),则可以说 #include <myheader.h> .
myheader.h
-I .
#include <myheader.h>
如果没有 -I 标志,则必须使用 #include "myheader.h" 来包含该文件,或将 myheader.h 移动到编译的 include 目录中 .
#include "myheader.h"
<file> include告诉预处理器在 -I 目录和预定义目录 first 中搜索,然后在.c文件的目录中搜索 . "file" include告诉预处理器搜索源文件的目录 first ,然后恢复为 -I 并预定义 . 无论如何都要搜索所有目的地,只有搜索顺序不同 .
<file>
"file"
2011标准主要讨论“16.2源文件包含”中的包含文件 .
2 #include <h-char-sequence> new-line形式的预处理指令搜索一系列实现定义的位置,用于由<和>分隔符之间的指定序列唯一标识的标头,并导致替换它指令由 Headers 的全部内容组成 . 如何指定位置或标识的标头是实现定义的 . 3形式#include“q-char-sequence”new-line的预处理指令使得该指令被“delimiters”之间指定序列标识的源文件的全部内容替换 . 搜索指定的源文件如果不支持此搜索,或者搜索失败,则重新处理该指令,就好像它读取#include <h-char-sequence> new-line一样,包含相同的序列(包括>字符,如果有的话)来自原始指令 .
请注意,如果找不到该文件, "xxx" 表单会降级为 <xxx> 表单 . 其余的是实现定义的 .
"xxx"
<xxx>
对于 #include "" ,编译器通常会搜索包含该文件的文件夹,然后搜索其他文件夹 . 对于 #include <> ,编译器不会搜索当前文件的文件夹 .
#include ""
#include <>
在引用系统文件时使用 #include <filename> . 这是一个头文件,可以在系统默认位置找到,如 /usr/include 或 /usr/local/include . 对于需要包含在另一个程序中的自己的文件,您必须使用 #include "filename" 语法 .
/usr/include
/usr/local/include
#include <filename> (1) #include "filename" (2)
#include 包括由文件名标识的源文件到紧接在该指令之后的行的当前源文件中 .
该指令的第一个版本仅搜索标准包含目录 . 标准C库以及标准C库隐式包含在标准包含目录中 . 标准包含目录可由用户通过编译器选项控制 . 第二个版本首先搜索当前文件所在的目录,并且只有在找不到该文件时才搜索标准的include目录 .
在如果找不到文件,程序就会格式不正确 .
如果头文件是预定义的,那么你只需在尖括号中编写头文件名,它就像这样(假设我们有一个预定义的头文件名iostream):
#include <iostream>
如果您(程序员)编写了自己的头文件,那么您可以在引号中编写头文件名 . 因此,假设您编写了一个名为 myfile.h 的头文件,那么这是一个如何使用include伪指令来包含该文件的示例:
myfile.h
#include "myfile.h"
至少对于GCC版本<= 3.0,角括号形式不会在包含文件和包含文件之间产生依赖关系 .
因此,如果要生成依赖性规则(使用GCC -M选项作为示例),则必须使用引用的表单来存储应该包含在依赖关系树中的文件 .
(见http://gcc.gnu.org/onlinedocs/cpp/Invocation.html)
#include <filename>当您想要使用C / C系统或编译器库的头文件时使用 . 这些库可以是stdio.h,string.h,math.h等 .#include "path-to-file/filename"当您想要使用项目文件夹中或其他位置的自定义头文件时使用 .
#include "path-to-file/filename"
有关预处理器和标头的更多信息 . 阅读C - Preprocessors .
实际上,区别在于预处理器搜索包含文件的位置 .
对于 #include <filename> ,预处理器以依赖于实现的方式搜索,通常在编译器/ IDE预先指定的搜索目录中 . 此方法通常用于包括标准库头文件 .
对于 #include "filename" ,预处理器首先在与包含该指令的文件相同的目录中进行搜索,然后按照用于 #include <filename> 表单的搜索路径进行搜索 . 此方法通常用于包括程序员定义的头文件 .
GCC documentation on search paths中提供了更完整的描述 .
“<filename>”在标准C库位置搜索,而“filename”也在当前目录中搜索 .
理想情况下,您可以将<...>用于标准C库,将“...”用于您编写并存在于当前目录中的库 .
#include "filename" // User defined header #include <filename> // Standard library header.
例:
这里的文件名是 Seller.h :
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 的其他文件),现在应包括用户定义的标头,如下所示:
Seller.cpp
#include "Seller.h"
唯一的方法是阅读您的实现文档 .
在the C standard,第6.10.2节,第2至4段指出:
<和>之间的字符序列唯一地引用 Headers ,该 Headers 不一定是文件 . 实现几乎可以随意使用字符序列 . (但是,大多数情况下,只需将其视为文件名并在包含路径中进行搜索,就像其他帖子所述 . )
如果使用 #include "file" 表单,则实现首先查找给定名称的文件(如果支持) . 如果不是(支持),或者搜索失败,则实现的行为就像使用了另一个( #include <file> )表单一样 .
#include <file>
此外,存在第三种形式,当 #include 指令与上述任何一种形式都不匹配时使用 . 在这种形式下,进行一些基本的预处理(例如宏扩展)在 #include 指令的"operands"上完成,结果预期与其他两种形式中的一种匹配 .
这里的一些好的答案引用了C标准,但忘记了POSIX标准,尤其是c99 (e.g. C compiler)命令的特定行为 .
根据The Open Group Base Specifications Issue 7,
-I directory更改搜索名称不是绝对路径名的标头的算法,以便在查看常用位置之前查看目录路径名所指定的目录 . 因此,名称以双引号(“”)括起来的 Headers 应首先在#include行的文件目录中搜索,然后在-I选项中命名的目录中搜索,最后在通常的位置搜索 . 对于名称用尖括号(“<>”)括起来的 Headers ,只能在-I选项中指定的目录中搜索 Headers ,然后在通常的位置搜索 Headers . 在-I选项中命名的目录应按指定的顺序进行搜索 . 实现应在单个c99命令调用中支持至少十个此选项的实例 .
因此,在符合POSIX的环境中,使用符合POSIX标准的C编译器, #include "file.h" 可能首先搜索 ./file.h ,其中 . 是具有 #include 语句的文件所在的目录,而 #include <file.h> 可能首先搜索 /usr/include/file.h ,其中 /usr/include 是您系统定义的标头常用位置(它似乎不是由POSIX定义的) .
#include "file.h"
./file.h
/usr/include/file.h
要使用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:Library / Developer / CommandLineTools / usr / bin“/ Library / Developer / CommandLineTools / usr / bin / clang“-cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror = deprecated-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-column -info -debugger-tuning = lldb -target-linker-version 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 -isysroot / Library / Developer / 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-diagnosis ostics -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(framework directory)搜索结束列表 .
30 回答
当您使用#include <filename>时,预处理器在C \ C头文件(stdio.h \ cstdio,string,vector等)的目录中查找文件 . 但是,当你使用#include“filename”时:首先,预处理器在当前目录中查找文件,如果它不在这里 - 他在C \ C头文件目录中查找它 .
在C中,以两种方式包含文件:
第一个是#include,它告诉预处理器在预定义的默认位置查找文件 . 此位置通常是INCLUDE环境变量,表示包含文件的路径 .
第二种类型是#include“filename”,它告诉预处理器首先在当前目录中查找文件,然后在用户设置的预定义位置查找它 .
编写#include语句有两种方法 . 这些是:
每种形式的含义是
此命令将查找当前目录中的文件
mylib.h
以及可能已设置的包含搜索路径中提到的指定目录列表 .此命令仅在指定的目录列表中查找文件
mylib.h
.包含搜索路径只是一个目录列表,可以搜索包含的文件 . 不同的C编译器允许您以不同的方式设置搜索路径 .
简单的一般规则是使用有角度的括号来包含编译器附带的头文件 . 使用双引号包含任何其他头文件 . 大多数编译器都是这样做的 .
1.9 — Header files更详细地解释了预处理器指令 . 如果您是新手程序员,该页面应该可以帮助您理解所有这些 . 我是从这里学到的,我一直在工作 .
它确实:
.
是包含#include
的文件的目录,和/或编译器的当前工作目录,和/或default_include_paths
和
如果
./
在<default_include_paths>
中,那么它没有什么区别 .如果
mypath/myfile
在另一个包含目录中,则行为未定义 .GCC documentation says以下关于两者的区别:
谢谢你的回答,特别是 . Adam Stelmaszczyk和piCookie,以及aib .
像许多程序员一样,我使用了
"myApp.hpp"
表单用于应用程序特定文件的非正式约定,以及用于库和编译器系统文件的<libHeader.hpp>
表单,即/I
和INCLUDE
环境变量中指定的文件,多年来一直认为这是标准 .但是,C标准规定搜索顺序是特定于实现的,这会使可移植性变得复杂 . 更糟糕的是,我们使用jam,它可以自动计算包含文件的位置 . 您可以为包含文件使用相对路径或绝对路径 . 即
较旧版本的MSVS需要双反斜杠(\),但现在不需要 . 我不知道它什么时候改变了 . 只需使用正斜杠与'nix兼容(Windows会接受) .
如果您真的很担心它,请将
"./myHeader.h"
用于与源代码位于同一目录中的包含文件(我当前的非常大的项目有一些重复的包含文件名分散 - 实际上是配置管理问题) .这是为了您的方便而复制的MSDN explanation .
按标准 - 是的,它们是不同的:
请注意,该标准没有说明实现定义方式之间的任何关系 . 第一种形式以一种实现定义的方式搜索,另一种以(可能是其他)实现定义的方式搜索 . 该标准还规定应存在某些包含文件(例如,
<stdio.h>
) .在正式情况下,您必须阅读编译器的手册,但通常(按传统),
#include "..."
表单会搜索首先找到#include
的文件的目录,然后搜索#include <...>
表单搜索的目录(包含路径,例如系统 Headers ) .带有尖括号的#include将搜索要包含的文件的“依赖于实现的位置列表”(这是一种非常复杂的说“系统头”的方式) .
带引号的#include将只搜索文件(并且,“以依赖于实现的方式”,bleh) . 这意味着,在普通英语中,它将尝试应用您在其上投掷的路径/文件名,并且不会预先添加系统路径或以其他方式篡改它 .
此外,如果#include“”失败,则标准将其重新读为#include <> .
gcc documentation有一个(编译器特定的)描述虽然特定于gcc而不是标准,但比ISO标准的律师风格的讨论要容易理解 .
搜索头文件的顺序不同 . <XXX.h>首先搜索标准 Headers ,而“XXX.h”首先搜索工作区的 Headers 文件 .
#include <filename>
将从C库中找到相应的文件 . 这意味着如果你在C库文件夹中有一个名为hello.h的文件,
#include <hello.h>
将加载它 .但,
#include "filename"
将在源文件所在的同一目录中找到该文件 .
此外,
#include "path_to_file/filename"
将在
path_to_file
中键入的目录中找到该文件 .用于包括标准库文件 . 因此,编译器将检查标准库头所在的位置 .
将告诉编译器包含用户定义的头文件 . 因此,编译器将检查当前文件夹或
-I
已定义文件夹中的这些头文件 .表格1 - #include“xxx”
首先,从where指令查找当前目录中是否存在头文件被调用 . 如果未找到,则在预配置的标准系统目录列表中搜索 .
表格2 - #include <xxx>
这将在调用where指令的当前目录中查找头文件的存在 .
确切的搜索目录列表取决于目标系统,GCC的配置方式以及安装位置 . 您可以通过使用-v选项运行GCC编译器的搜索目录列表 .
您可以使用 - Idir将其他目录添加到搜索路径,这会导致在当前目录(对于指令的引用形式)之后和标准系统目录之前搜索dir .
基本上,“xxx”形式只是在当前目录中搜索;如果没有找到退回形式
我相信包含在双引号中的 Headers 将在相同的系统路径中查找,如果在当前目录中找不到它们,则包括angle-bracketed .
这里的许多答案都集中在编译器为了找到文件而搜索的路径上 . 虽然这是大多数编译器所做的,但是允许符合标准的编译器使用标准头的效果进行预编程,并将
#include <list>
视为一个开关,它根本不需要作为文件存在 .这不是纯粹的假设 . 至少有一个编译器以这种方式工作 . 建议仅使用标准 Headers
#include <xxx>
.#include <file.h>
告诉编译器在其"includes"目录中搜索 Headers ,例如对于MinGW,编译器将在C:\ MinGW \ include \或安装编译器的任何地方搜索file.h
.#include "file"
告诉编译器搜索file
的当前目录(即源文件所在的目录) .您可以使用GCC的
-I
标志告诉它,当遇到包含斜角括号的包含时,它还应该在-I
之后搜索目录中的 Headers . GCC会将标志后的目录视为includes
目录 .例如,如果您在自己的目录中有一个名为
myheader.h
的文件,如果您使用标志-I .
调用GCC(表示它应该在当前目录中搜索包含),则可以说#include <myheader.h>
.如果没有
-I
标志,则必须使用#include "myheader.h"
来包含该文件,或将myheader.h
移动到编译的include
目录中 .<file>
include告诉预处理器在-I
目录和预定义目录 first 中搜索,然后在.c文件的目录中搜索 ."file"
include告诉预处理器搜索源文件的目录 first ,然后恢复为-I
并预定义 . 无论如何都要搜索所有目的地,只有搜索顺序不同 .2011标准主要讨论“16.2源文件包含”中的包含文件 .
请注意,如果找不到该文件,
"xxx"
表单会降级为<xxx>
表单 . 其余的是实现定义的 .对于
#include ""
,编译器通常会搜索包含该文件的文件夹,然后搜索其他文件夹 . 对于#include <>
,编译器不会搜索当前文件的文件夹 .在引用系统文件时使用
#include <filename>
. 这是一个头文件,可以在系统默认位置找到,如/usr/include
或/usr/local/include
. 对于需要包含在另一个程序中的自己的文件,您必须使用#include "filename"
语法 .#include
包括由文件名标识的源文件到紧接在该指令之后的行的当前源文件中 .在如果找不到文件,程序就会格式不正确 .
如果头文件是预定义的,那么你只需在尖括号中编写头文件名,它就像这样(假设我们有一个预定义的头文件名iostream):
如果您(程序员)编写了自己的头文件,那么您可以在引号中编写头文件名 . 因此,假设您编写了一个名为
myfile.h
的头文件,那么这是一个如何使用include伪指令来包含该文件的示例:至少对于GCC版本<= 3.0,角括号形式不会在包含文件和包含文件之间产生依赖关系 .
因此,如果要生成依赖性规则(使用GCC -M选项作为示例),则必须使用引用的表单来存储应该包含在依赖关系树中的文件 .
(见http://gcc.gnu.org/onlinedocs/cpp/Invocation.html)
#include <filename>
当您想要使用C / C系统或编译器库的头文件时使用 . 这些库可以是stdio.h,string.h,math.h等 .
#include "path-to-file/filename"
当您想要使用项目文件夹中或其他位置的自定义头文件时使用 .
有关预处理器和标头的更多信息 . 阅读C - Preprocessors .
实际上,区别在于预处理器搜索包含文件的位置 .
对于
#include <filename>
,预处理器以依赖于实现的方式搜索,通常在编译器/ IDE预先指定的搜索目录中 . 此方法通常用于包括标准库头文件 .对于
#include "filename"
,预处理器首先在与包含该指令的文件相同的目录中进行搜索,然后按照用于#include <filename>
表单的搜索路径进行搜索 . 此方法通常用于包括程序员定义的头文件 .GCC documentation on search paths中提供了更完整的描述 .
理想情况下,您可以将<...>用于标准C库,将“...”用于您编写并存在于当前目录中的库 .
例:
这里的文件名是
Seller.h
:在类实现中(例如,
Seller.cpp
,以及将使用文件Seller.h
的其他文件),现在应包括用户定义的标头,如下所示:唯一的方法是阅读您的实现文档 .
在the C standard,第6.10.2节,第2至4段指出:
<和>之间的字符序列唯一地引用 Headers ,该 Headers 不一定是文件 . 实现几乎可以随意使用字符序列 . (但是,大多数情况下,只需将其视为文件名并在包含路径中进行搜索,就像其他帖子所述 . )
如果使用
#include "file"
表单,则实现首先查找给定名称的文件(如果支持) . 如果不是(支持),或者搜索失败,则实现的行为就像使用了另一个(#include <file>
)表单一样 .此外,存在第三种形式,当
#include
指令与上述任何一种形式都不匹配时使用 . 在这种形式下,进行一些基本的预处理(例如宏扩展)在#include
指令的"operands"上完成,结果预期与其他两种形式中的一种匹配 .这里的一些好的答案引用了C标准,但忘记了POSIX标准,尤其是c99 (e.g. C compiler)命令的特定行为 .
根据The Open Group Base Specifications Issue 7,
因此,在符合POSIX的环境中,使用符合POSIX标准的C编译器,
#include "file.h"
可能首先搜索./file.h
,其中.
是具有#include
语句的文件所在的目录,而#include <file.h>
可能首先搜索/usr/include/file.h
,其中/usr/include
是您系统定义的标头常用位置(它似乎不是由POSIX定义的) .要使用gcc查看系统上的搜索顺序,请根据当前配置执行以下命令 . 你可以在这个命令上找到更多细节here
cpp -v /dev/null -o /dev/null