#include < 文件名>和 #include“文件名”有什么区别?

What is the difference between #include <filename> and #include "filename"?

提问人:quest49 提问时间:8/22/2008 最后编辑:Mateen Ulhaqquest49 更新时间:8/11/2022 访问量:883783

问:

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

  • #include <filename>
  • #include "filename"
C++ 包含 头文件 C-preprocessor

评论

24赞 legends2k 6/5/2013
gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC6
2赞 theoretisch 8/10/2016
GCC 在哪里查找其头文件
3赞 smwikipedia 3/17/2020
有关 Visual Studio 的行为,请查看:learn.microsoft.com/en-us/cpp/preprocessor/...
1赞 Adam 12/1/2022
这样的问题怎么会有这么多的赞成票?是有投票规则的吗?

答:

1871赞 quest49 8/22/2008 #1

不同的是预处理器搜索要包含的文件的位置。

  • #include <filename>预处理器以实现定义的方式进行搜索,通常在编译器/IDE 预先指定的目录中进行搜索。此方法通常用于包含 C 标准库的头文件以及与目标平台关联的其他头文件。

  • #include "filename"预处理器还以实现定义的方式进行搜索,但通常用于包含程序员定义的头文件,并且通常包含与包含指令的文件相同的目录(除非给出了绝对路径)。

对于 GCC,有关搜索路径的 GCC 文档中提供了更完整的说明。

评论

169赞 Richard Corden 9/17/2008
语句:“预处理器在同一目录中搜索...”在实践中可能是正确的,但该标准规定命名的源文件是“以实现定义的方式搜索的”。请参阅piCookie的答案。
84赞 Dan Moulding 8/18/2009
虽然你的答案可能看起来是“真的”,因为这是许多按照惯例工作的实现,你应该仔细看看 aib 和 piCookie 的答案。他们都指出(以 C 标准的措辞为后盾),真正的区别在于包含“标头”与包含“源文件”(不,这并不意味着“.h”与“.c”)。在此上下文中,“源文件”可以是(通常是,而且几乎总是应该)是“.h”文件。标头不一定是文件(例如,编译器可以包含静态编码的标头,而不是在文件中)。
6赞 Gabriel Southern 3/13/2012
"...预处理器在与正在编译的文件相同的目录中搜索要包含的文件。这种说法并不完全正确。我对这个问题很感兴趣,因为我很好奇实际的答案是什么,但我知道这不是真的,因为至少在 gcc 中,当您使用 -I 指定一个额外的包含路径时,该路径将搜索 #include“filename.h”指定的文件
18赞 0kcats 11/9/2017
那些不喜欢这个答案的人,请举一个实际的例子,哪里是错误的。
7赞 paxdiablo 1/10/2020
“一个错误的实际例子”是无关紧要的。标准的存在是有原因的。准则(在标准中)是用于实现中包含的标头,用于其他所有内容。但很明显,这只是一个指南,这两种情况的搜索路径都是实现定义的,如果找不到,事实将回退。<>""""<>
46赞 user3458 9/3/2008 #2

include 告诉预处理器首先在目录和预定义目录中搜索,然后在 .c 文件的目录中搜索。include 告诉预处理器首先搜索源文件的目录,然后恢复到预定义。无论如何,都会搜索所有目的地,只是搜索顺序不同。<file>-I"file"-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>

评论

7赞 juanchopanza 12/28/2014
您能否提供参考,说明该业务在 C 标准中的位置?-I
2赞 juanchopanza 12/29/2014
我没有看到提到.-I
2赞 12/29/2014
这是“实现定义”的部分。
0赞 mnr 7/1/2021
“反正所有目的地都被搜索了,只是搜索顺序不同。”那么,如果我尝试使用 mingw 编译我的程序,如果我包含 < >它就找不到我的头文件,但使用 “ ” 它确实可以找到它。
353赞 aib 9/9/2008 #3

< 和 > 之间的字符序列唯一引用标头,而标头不一定是文件。实现几乎可以自由地使用字符序列,如他们所愿。(但是,大多数情况下,只需将其视为文件名,并在包含路径中进行搜索,就像其他帖子所述。

如果使用表单,则实现将首先查找给定名称的文件(如果支持)。如果不支持,或者搜索失败,则实现的行为就像使用了其他 () 形式一样。#include "file"#include <file>

此外,存在第三种形式,当指令与上述任一形式不匹配时使用。在这种形式中,一些基本的预处理(如宏扩展)是在指令的“操作数”上完成的,结果应该与其他两种形式之一相匹配。#include#include

评论

61赞 Dan Moulding 8/18/2009
+1,这可能是这里最简洁、最正确的答案。根据标准(piCookie在他的回答中引用了这个标准),唯一真正的区别是“头文件”与“源文件”。无论哪种方式,搜索机制都是由实现定义的。使用双引号意味着您打算包含“源文件”,而尖括号意味着您打算包含一个“标题”,正如您所说,它可能根本不是文件。
3赞 aib 1/27/2011
参见 Dan Moulding 对 quest49 答案的评论;标准标头不必采用文件形式,它们可以是内置的。
16赞 Maxim Egorushkin 2/8/2011
十年来,我一直在阅读这句“标准标头不必是文件形式”。想提供一个真实世界的例子吗?
16赞 Dan Moulding 10/12/2012
@Maxim 叶戈鲁什金:我也想不出任何现成的现实世界的例子;但是,MS-DOS 不能存在完整的 C11 编译器,除非标头不必是文件。这是因为某些 C11 标头名称与“8.3”MS-DOS 文件名限制不兼容。
32赞 Adrian McCarthy 2/16/2017
@MaximEgorushkin:VAX/VMS C 编译器将所有 C 运行时库头文件保存在一个文本库文件(类似于 unix 存档)中,并使用 和 之间的字符串作为索引到库中的键。<>
829赞 piCookie 9/17/2008 #4

了解的唯一方法是阅读实现的文档。

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<>"

定义:

  • h-char:源字符集的任何成员,换行符和>

  • q-char:源字符集的任何成员,换行符和"

评论

127赞 Alexander Malakhov 10/10/2012
相关:在 g++ 和 Visual C++ 中实现
38赞 onmyway133 2/4/2013
@piCookie<文件名>和“文件名”都搜索实现定义的位置。那么有什么区别呢?
18赞 piCookie 8/25/2013
@Stefan,我只是引用标准,它没有提到INCLUDE_PATH。你的实现可能会做到这一点,而我的可能不会。最初的问题一般是 C,而不是专门使用 gcc(我认为它不使用 INCLUDE_PATH)或 Microsoft C(我认为确实如此)或任何其他问题,因此不能笼统地回答,而是必须引用每个实现的文档。
21赞 vargonian 4/30/2014
与所有这些情况一样,具体的例子(尤其是常见情况)非常有用,同样值得赞赏。不必要的迟钝的通用答案没有那么多的实际用途。
185赞 anatolyg 3/30/2015
“这就是 C 标准如何冗长而不回答你的问题”
52赞 Stefan Steiger 2/8/2011 #5

它确实:

"mypath/myfile" is short for ./mypath/myfile

,作为包含 和/或编译器的当前工作目录的文件的目录,和/或.#includedefault_include_paths

<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile

如果在 中,则没有区别。./<default_include_paths>

如果位于另一个包含目录中,则行为未定义。mypath/myfile

评论

18赞 Keith Thompson 9/8/2011
不,不等同于 。正如 piCookie 的回答所说,双引号告诉编译器以实现定义的方式进行搜索——这包括在为 .(实际上,它可能是等价的,但只是因为,例如,可以称为 -- 至少在类 Unix 系统上是这样。#include "mypath/myfile"#include "./mypath/myfile"#include <...>/usr/include/mypath/myfile/usr/include/./mypath/myfile
1赞 Stefan Steiger 4/3/2014
@Keith Thompson:没错,我在想我的 Linux 机器。显然,情况可能会有所不同。虽然在实践中,Windows 作为非 Posix 操作系统也确实将 / 解释为路径分隔符,并且 ./ 也存在。
1赞 Protongun 4/7/2014
然后,-L dirpath 选项将 dirpath 添加到 中,而不是赋予 (如上所述)另一种含义。这会产生预期的结果,即在 dirpath 中搜索defaultincludepaths.#include "..."#include <...>
1赞 Carlo Wood 9/28/2016
我认为这个答案是不正确的,因为它意味着始终在当前工作目录中查找包含双引号的标题。搜索机制更加详细;这个答案是不完整的。我添加此评论不是为了抱怨或抱怨,而是因为系统要求我添加评论来解释为什么我投票否决了这个答案。
20赞 Maxim Egorushkin 2/8/2011 #6

对于编译器来说,通常会搜索包含该包含的文件的文件夹,然后搜索其他文件夹。因为编译器不搜索当前文件的文件夹。#include ""#include <>

评论

1赞 Maxim Egorushkin 3/27/2012
不知道为什么人们不同意。
0赞 3/30/2012
我怀疑这是因为大多数人只编译 CWD 中的文件。如果你在目录 foo 中,并且你正在编译 foo/unittest/bar.c,并且它包含 bar.h,那么 “bar.h” 有效,而 <bar.h> 则无效。
2赞 osvein 7/25/2015
@Maxim不同意,因为你描述的行为不是标准的C。
4赞 Maxim Egorushkin 9/17/2016
@Spookbuster 是的,标准说两者兼而有之,并搜索实现定义的地方。<filename>"filename"
15赞 Damon 2/8/2011 #7

带有尖括号的 #include 将搜索“与实现相关的位置列表”(这是“系统标头”的一种非常复杂的表示方式)以包含文件。

带引号的 #include 只会搜索一个文件(并且,“以依赖于实现的方式”,咩)。这意味着,在普通英语中,它将尝试应用您抛给它的路径/文件名,并且不会在系统路径之前添加或篡改它。

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

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

评论

0赞 Loghorn 2/8/2011
但是,使用尖括号或引号不会影响文件的包含方式,它是完全相同的:预处理器通过复制粘贴代码从包含文件到原始源文件来创建大型源文件,然后再将其提供给编译器(预处理器执行其他操作,例如 #define 支持、#if 评估等,但 #include 处理就这么简单)
0赞 the_mandrill 2/8/2011
冲突呢?例如,假设我在我的“用户”搜索路径中,并且系统搜索路径中存在不同的版本,那么是否包括系统版本并包含我自己的版本?zlib.h#include <zlib.h>#include "zlib.h"
0赞 the_mandrill 2/8/2011
啊哈,回答了我自己的问题:stackoverflow.com/questions/21593/......
0赞 Kyle Strand 7/28/2016
感谢您承认标准典型的实现约定在这里都是相关的,而不是简单地说它是不可知的,因为它没有被标准指定。
11赞 Barbara 9/29/2011 #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.cppSeller.h

#include "Seller.h"
22赞 Denis Ros 10/25/2011 #9

至少对于 GCC 版本 <= 3.0,尖括号形式不会在包含的文件和包含的文件之间生成依赖关系。

因此,如果要生成依赖关系规则(例如使用 GCC -M 选项),则必须对应包含在依赖关系树中的文件使用带引号的表单。

(见 http://gcc.gnu.org/onlinedocs/cpp/Invocation.html )

评论

1赞 Pryftan 11/22/2019
是的 - 有几种不同的方法可以生成依赖项。这是其中之一,但不是唯一的。
138赞 Yann Droneaud 7/20/2012 #10

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

根据 The Open Group Base Specifications Issue 7

-I 目录

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

因此,在符合 POSIX 的环境中,使用符合 POSIX 的 C 编译器,可能会首先搜索 where,where 是带有语句的文件的目录,而 ,可能会首先搜索,where 是您的系统定义的标头的通常位置(它似乎不是由 POSIX 定义的)。#include "file.h"./file.h.#include#include <file.h>/usr/include/file.h/usr/include

评论

1赞 osgx 3/12/2015
文本的确切来源是什么?它是否来自 IEEE Std 1003.1, 2013 的规范部分?
8赞 Jonathan Leffler 11/10/2016
@osgx:这个措辞(或极其相似的东西)可以在 c99 的 POSIX 规范中找到——这是 C 编译器的 POSIX 名称。(POSIX 2008 标准几乎不能引用 C11;2013 年对 POSIX 2008 的更新并没有改变它所引用的 C 标准。
1赞 Pryftan 11/22/2019
这也是我的第一个想法。gcc 的手册页和其他手册页一样包括此内容。对于库来说,也有类似的事情 - .-L
12赞 AndroidDev 12/17/2012 #11
  • #include <> 用于预定义的头文件

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

#include <iostream>
  • #include “ ” 表示程序员定义的头文件

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

#include "myfile.h"

评论

3赞 C.J. 4/23/2019
它与预定义的头文件完全无关。它与要搜索的位置有关。
0赞 PRouleau 6/30/2022
这个问题比你的答案更笼统,它只解决了 C++ 的一个方面,而忽略了 C。我同意 C Jonhson 的观点。C++ 确实支持无扩展名标头(这对某些工具来说是一个真正的痛苦,顺便说一句),但它也可用于识别将使用特定于实现的方式搜索的文件,如其他答案中所述。
5赞 Eakan Gopalakrishnan 6/4/2013 #12

简单的一般规则是使用尖括号来包含编译器附带的头文件。使用双引号包含任何其他头文件。大多数编译器都是这样做的。

1.9 – 头文件更详细地解释了预处理器指令。如果你是一个新手程序员,该页面应该可以帮助你理解所有这些。我从这里学到了它,我一直在工作中遵循它。

13赞 sp2danny 2/25/2014 #13

这里的许多答案都集中在编译器为了查找文件而搜索的路径上。虽然这是大多数编译器所做的,但允许使用标准头文件的效果对符合要求的编译器进行预编程,并将其视为开关,并且根本不需要作为文件存在。#include <list>

这不是纯粹的假设。至少有一个编译器以这种方式工作。建议仅与标准标头一起使用。#include <xxx>

评论

0赞 supercat 3/16/2021
与此相关的是,该标准没有说明实现必须在文件名中接受哪些字符,也没有说明实现必须接受的文件名长度。符合要求的实现可以在文件名限制为六个字母数字字符的文件系统上运行,并拒绝文件名包含句点形式的任何指令,但符合要求的实现必须接受例如“#include < float.h>”,而不考虑是否是有效的文件名。#include "fname"float.h
6赞 srsci 8/28/2014 #14

在引用系统文件时使用 。这是一个头文件,可以在系统默认位置找到,如 或 。对于需要包含在另一个程序中的您自己的文件,您必须使用语法。#include <filename>/usr/include/usr/local/include#include "filename"

19赞 riderBill 10/15/2014 #15

感谢您的精彩回答,尤其是 Adam Stelmaszczyk 和 piCookie,以及 aib。

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

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

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

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

如果您真的担心它,请使用与源代码位于同一目录中的包含文件(我当前非常大的项目有一些重复的包含文件名散落在各处 - 实际上是一个配置管理问题)。"./myHeader.h"

为方便起见,此处复制了 MSDN 说明)。

报价表格

预处理器按以下顺序搜索包含文件:

  1. 与包含 #include 语句的文件位于同一目录中。
  2. 在当前打开的包含文件的目录中,按
    打开它们的相反顺序排列。搜索从父包含文件的目录开始,并继续
    向上搜索任何父包含文件的目录。
  3. 沿着每个编译器选项指定的路径。/I
  4. 沿着环境变量指定的路径。INCLUDE

尖括号形式

预处理器按以下顺序搜索包含文件:

  1. 沿着每个编译器选项指定的路径。/I
  2. 在命令行上进行编译时,沿环境变量指定的路径进行编译。INCLUDE
5赞 Hafiz Shehbaz Ali 4/3/2015 #16
#include <filename>

当您要使用 C/C++ 系统或编译器库的头文件时使用。这些库可以是 stdio.h、string.h、math.h 等。

#include "path-to-file/filename"

当您想要使用自己的自定义头文件(位于项目文件夹或其他位置)时,会使用。

有关预处理器和标头的详细信息。阅读 C - 预处理器

26赞 skyking 8/18/2015 #17

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

  • 表单的预处理指令

    #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 <...>

评论

3赞 Kyle Strand 7/28/2016
这与piCookie七年前的回答大致相同。
6赞 skyking 7/28/2016
@KyleStrand 这是因为相同的文本是标准中相关部分的引用 - 该文本应该是相同的。实际的答案不是相同的文本,并且有些不同 - 虽然我也认识到它将写在实现的文档中,但我也注意到还有一种传统的解释方式(我使用的大多数或所有编译器都尊重)。
2赞 plugwash 9/11/2016
IMO 这是这里最好的答案,因为它涵盖了标准所说的内容和大多数编译器实际执行的操作。
7赞 virat 2/17/2016 #18

在 C++ 中,以两种方式包含文件:

第一个是 #include 它告诉预处理器在预定义的默认位置查找文件。 此位置通常是一个 INCLUDE 环境变量,表示包含文件的路径。

第二种类型是 #include“文件名”,它告诉预处理器首先在当前目录中查找文件,然后在用户设置的预定义位置查找它。

60赞 Suraj Jain 1/14/2017 #19

GCC 文档对两者之间的区别进行了如下说明:

用户和系统头文件都使用预处理指令“#include”包含在内。它有两种变体:

#include <file>

此变体用于系统头文件。它在系统目录的标准列表中搜索名为 file 的文件。您可以使用以下选项将目录附加到此列表前面(请参阅调用)。-I

#include "file"

此变体用于您自己程序的头文件。它首先在包含当前文件的目录中搜索名为 file 的文件,然后在 quote 目录中搜索,最后在用于 的相同目录中搜索 。您可以使用该选项将目录附加到报价目录列表的前面。 的参数,无论是用引号还是尖括号分隔,其行为都类似于字符串常量,因为无法识别注释,并且不会展开宏名称。因此,指定包含名为 的系统头文件。<file>-iquote‘#include’#include <x/*y>x/*y

但是,如果反斜杠出现在文件中,则它们被视为普通文本字符,而不是转义字符。不处理任何适合 C 中字符串常量的字符转义序列。因此,指定包含三个反斜杠的文件名。(某些系统将“\”解释为路径名分隔符。所有这些也以同样的方式解释。它是最便携的,只能使用。#include "x\n\\y"‘/’‘/’

如果文件名后面的行上有任何内容(注释除外),则为错误。

评论

0赞 Jack M 7/30/2020
什么是“报价目录”?
0赞 Eljay 8/2/2020
@JackM • 有 3 个位置:-ing 文件的当前目录、引用目录(检查样式包含的路径)和系统目录(检查样式包含的路径)。#include#include "foo.h"#include <bar.h>
0赞 littleO 11/15/2020
短语“系统头文件”中的“系统”是什么意思?我发现计算机科学家经常使用“系统”这个词,我经常分不清它是“操作系统”、“计算机系统”还是其他什么。
1赞 9/17/2021
这是最好的答案。这个话题可以无限地讨论数年甚至数十年,但编译器的明显趋势是 <> 用于系统头文件,而 “ ” 用于本地目录和项目头文件。我将 <> 用于系统标头,将 “ ” 用于其他所有内容。这样,在代码中就可以清楚地知道标头是否为系统标头。另外,这样一来,如果在更改代码时将本地项目头移动到不同的目录,则无需将“ ”更改为<>,反之亦然。(PS:这也是 ReSharper C++ 方法,会自动为您包含标头)。
1赞 Bill Gale 10/8/2021
我同意这是最好的答案。为了澄清起见,对我来说,系统文件是您没有编写的任何内容,并且正在引用,当然您的编译器包括,但除此之外,任何其他已安装的软件包。还有你写的程序文件。使用 Google protobufs,系统文件将是 <google/protobuf/type_pb.h>,程序文件将是 protobuf “mydir/my_pb.h”。
11赞 Christy Wald 1/23/2017 #20
#include <abc.h>

用于包含标准库文件。因此,编译器将签入标准库头文件所在的位置。

#include "xyz.h"

将告诉编译器包含用户定义的头文件。因此,编译器将在当前文件夹或定义的文件夹中检查这些头文件。-I

76赞 adrian 3/12/2018 #21

预处理器的确切行为因编译器而异。以下答案适用于 GCC 和其他几个编译器。

#include <file.h>告诉编译器在其“includes”目录中搜索标头,例如,编译器将在 C:\MinGW\include\ 或编译器安装的任何位置搜索 MinGW。file.h

#include "file"指示编译器在当前目录(即源文件所在的目录)中搜索 。file

您可以使用 GCC 的标志来告诉它,当它遇到带尖括号的包含时,它还应该在 之后的目录中搜索标头。GCC 会将标志后面的目录视为目录。-I-Iincludes

例如,如果你在自己的目录中调用了一个文件,你可以说你是否调用了带有标志的 GCC(表示它应该在当前目录中搜索 includes)。myheader.h#include <myheader.h>-I .

如果没有该标志,则必须使用该标志来包含文件,或移动到编译器的目录。-I#include "myheader.h"myheader.hinclude

评论

1赞 d512 12/23/2021
疯狂的是,很少有人(包括我自己)了解用 C/C++ 开发如此基本的东西。记录不严的公约的暴政。
0赞 Cloud Cho 11/15/2023
中方能否分享任何参考资料?
4赞 Jigar Karangiya 3/28/2018 #22

“<文件名>”在标准 C 库位置进行搜索

而“filename”也在当前目录中搜索。

理想情况下,您会使用<...>标准 C 库和“...”对于您编写并存在于当前目录中的库。

评论

5赞 Daniel Langr 3/28/2018
哪些新信息将这个答案添加到其他答案中?
6赞 Darshan L 8/17/2018 #23

表格 1 - #include < xxx >

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

表格 2 - #include “xxx”

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


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

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


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

评论

3赞 Jonathan Leffler 7/13/2019
如果您决定回答一个已经确定且正确答案的旧问题,那么在当天晚些时候添加新答案可能不会给您带来任何积分。如果你有一些独特的新信息,或者你确信其他答案都是错误的,一定要添加一个新答案,但是在问题被问到很久之后,“另一个答案”给出相同的基本信息通常不会为你赢得太多的信任。
2赞 personal_cloud 7/13/2019
@Jonathan Leffler:你能给我指出一个你认为和Darshan的答案一样简洁准确的“公认”答案吗?
2赞 Jonathan Leffler 7/13/2019
@personal_cloud,表格的描述不准确。我认为 piCookieYann Droneaud 的答案最相关,因为他们确定了他们的信息来自哪里。我也不认为得票最高的答案完全令人满意。#include "header.h"
1赞 Neonit 8/1/2019
为什么这个答案显示在顶部,而再往下有两个答案是 650+ 票?这个答案让我感到困惑,因为它与我观察到的行为不符。这可能是因为最后一句由于没有转义尖括号而被破坏。我不确定这应该是什么意思。
-5赞 LocalHost 8/18/2018 #24

有两种方法可以编写 #include 语句。这些是:

#include"filename"
#include<filename>

每种形式的含义是

#include"mylib.h"

此命令将在当前目录中查找文件,以及可能已设置的包含搜索路径中提到的指定目录列表。mylib.h

#include<mylib.h>

此命令将仅在指定的目录列表中查找文件。mylib.h

包含搜索路径只不过是要搜索要包含的文件的目录列表。不同的 C 编译器允许您以不同的方式设置搜索路径。

评论

5赞 Jonathan Leffler 7/13/2019
如果您决定回答一个已经确定且正确答案的旧问题,那么在当天晚些时候添加新答案可能不会给您带来任何积分。如果你有一些独特的新信息,或者你确信其他答案都是错误的,一定要添加一个新答案,但是在问题被问到很久之后,“另一个答案”给出相同的基本信息通常不会为你赢得太多的信任。
0赞 IInspectable 12/29/2022
除了明显错误的“信息”之外,答案中没有任何新内容(根本不需要 -directive 将其参数解释为文件)。这种贡献根本没有用。既定的答案既更完整,也更少错误。#include
3赞 Hogstrom 10/4/2018 #25

要使用 gcc 查看系统上的搜索顺序,请根据当前配置执行以下命令。您可以在此处找到有关此命令的更多详细信息

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=已弃用的objc-isa-usage-E-禁用免费-disable-llvm-验证者-discard-value-names-main-file-namenull -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 /资源库/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-diagnostics -traditional-cpp -o - -x c /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 (框架 directory)
搜索列表末尾。

5赞 Kalana 12/27/2019 #26

#include <filename>

  • 预处理器以与实现相关的方式进行搜索。它告诉编译器搜索保存系统头文件的目录。
  • 此方法通常用于查找标准头文件。

#include "filename"

  • 这告诉编译器搜索运行程序的头文件。如果失败,它的行为类似于在存储系统头文件的位置搜索该头文件。#include <filename>
  • 该方法通常用于识别用户定义的头文件(由用户创建的头文件)。如果您想调用标准库,请不要使用它,因为它比 .#include <filename>
8赞 IAmAUser 3/2/2020 #27
#include <file> 

包括默认包含目录所在的文件。

#include "file" 

包括编译该文件的当前目录中的文件。双引号也可以指定不同位置的完整文件路径。

4赞 Saptarshi das 11/24/2020 #28

通常,区别在于预处理器搜索头文件的位置:

#include 是包含头文件的预处理器指令。这两个 #include 都用于在程序中添加或包含头文件,但首先是包含系统头文件,然后是用户定义的头文件。

  1. #include < filename> 用于在程序中包含系统库头文件,表示 C/C++ 预处理器将搜索存储 C 库文件或存储预定义系统头文件的文件名。
  2. #include“filename”用于在程序中包含用户定义的头文件,则表示 C/C++ 预处理器将在程序所在的当前目录中搜索文件名,然后遵循用于 #include < filename 的搜索路径>

查看 gcc 文档 gcc include 文件

8赞 Paul Yang 2/28/2021 #29

""将首先搜索。然后搜索默认包含路径。 您可以使用如下命令来打印默认的包含路径:./

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
#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

// d.c
#include <stdio.h>
#include "stdio.h"
int main()
{
        int a = 0;

        a = foo();

        printf("a=%d\n", a);

        return 0;
}
-1赞 david 7/9/2021 #30

编译器生成的实现定义的警告可以(并且将)以不同的方式对待系统库和程序库。

所以

#include <myFilename>

-- 这实际上声明了 myFilename 位于系统库位置 -- 可能(并且可能会)隐藏死代码和未使用的变量警告等,当您使用时会显示:

#include "myFilename"

评论

2赞 Nathan Reed 8/20/2021
这是不正确的。虽然编译器确实以不同的方式处理系统标头,但该行为不是通过在 中使用尖括号来触发的,而是由标头位于特定系统目录中触发的。请参阅有关该主题的 gccMicrosoft 文档。#include
0赞 david 8/21/2021
@Nathan-Reed 再次阅读您的来源,尝试理解它们的含义,然后删除您的评论。
2赞 Nathan Reed 8/22/2021
我建议你重新阅读来源。同样,在 中使用尖括号不会触发系统标头行为,正如您的答案所声称的那样。唯一的例外是带有标志的 VS,这是非默认的。#include/external:anglebrackets