在 C 和 C++ 编程语言中,在include语句中使用尖括号和使用引号有什么区别,如下所示?

  1. #include <filename>
  2. #include "filename"

===============>>#1 票数:1606

实际上,区别在于预处理器搜索包含文件的位置。

对于#include <filename> ,预处理器以依赖于实现的方式搜索,通常在编译器/IDE 预先指定的搜索目录中。 此方法通常用于包含标准库头文件。

对于#include "filename" ,预处理器首先在与包含指令的文件相同的目录中搜索,然后遵循用于#include <filename>表单的搜索路径。 此方法通常用于包含程序员定义的头文件。

关于搜索路径的 GCC文档中提供了更完整的描述。

===============>>#2 票数:769

知道的唯一方法是阅读您的实现文档。

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:源字符集的任何成员,除了换行符和"

===============>>#3 票数:312

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

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

此外,存在第三种形式,当#include指令与上述任何一种形式都不匹配时使用。 在这种形式中,对#include指令的“操作数”进行了一些基本的预处理(例如宏扩展),并且预期结果与其他两种形式之一匹配。

===============>>#4 票数:123

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

根据The Open Group Base Specification Issue 7

-I目录

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

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

===============>>#5 票数:52

GCC 文档说明了以下两者之间的区别:

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

#include <file>

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

#include "file"

此变体用于您自己程序的头文件。 它首先在包含当前文件的目录中搜索名为 file 的文件,然后在引用目录中搜索,然后在用于<file>的相同目录中搜索。 您可以使用-iquote选项将目录添加到引用目录列表中。 '#include'的参数,无论是用引号还是尖括号分隔,都表现得像一个字符串常量,因为注释不被识别,宏名称不被扩展。 因此, #include <x/*y>指定包含名为x/*y的系统头文件。

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

如果文件名后的行中有任何内容(注释除外),则这是一个错误。

===============>>#6 票数:52

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

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

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

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

例如,如果您在自己的目录中有一个名为myheader.h的文件,并且您使用标志-I .调用 GCC,则可以说#include <myheader.h> -I . (表示它应该在当前目录中搜索包含。)

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

===============>>#7 票数:46

它确实:

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

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

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

如果./<default_include_paths> ,那么它没有区别。

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

===============>>#8 票数:39

<file>包含告诉预处理器搜索-I目录和在预定义的目录第一,然后在.c文件的目录。 "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>形式。 其余的是实现定义的。

===============>>#9 票数:23

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

  • 形式的预处理指令

    #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 <...>表单搜索(包含路径,例如系统标题)。

===============>>#10 票数:18

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

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

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

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

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

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

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

引用形式

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

  1. 在与包含 #include 语句的文件相同的目录中。
  2. 在当前打开的包含文件的目录中,以相反的顺序
    他们被打开了。 搜索从父包含文件的目录开始,然后
    继续向上遍历任何祖父包含文件的目录。
  3. 沿着每个/I编译器选项指定的路径。
  4. 沿着由INCLUDE环境变量指定的路径。

角括号形式

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

  1. 沿着每个/I编译器选项指定的路径。
  2. 当编译发生在命令行上时,沿着由INCLUDE环境变量指定的路径。

===============>>#11 票数:18

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

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

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

===============>>#12 票数:17

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

===============>>#13 票数:14

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

带引号的 #include 将只搜索文件(并且“以依赖于实现的方式”,bleh)。 这意味着,在普通英语中,它会尝试应用您在其上折腾的路径/文件名,并且不会预先添加系统路径或以其他方式篡改它。

此外,如果 #include "" 失败,它会被标准重新读取为 #include <>。

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

===============>>#14 票数:14

当您使用#include <filename> 时,预处理器会在 C\\C++ 头文件(stdio.h\\cstdio、字符串、向量等)的目录中查找文件。 但是,当您使用 #include "filename" 时:首先,预处理器在当前目录中查找文件,如果它不在此处 - 他在 C\\C++ 头文件目录中查找它。

===============>>#15 票数:12

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

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

#include <iostream>
  • #include " "用于程序员定义的头文件

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

#include "myfile.h"

===============>>#16 票数:12

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

这不完全是假设。 至少有一个编译器以这种方式工作。 建议仅对标准头文件使用#include <xxx>

===============>>#17 票数:10

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

===============>>#18 票数:9

#include <abc.h>

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

#include "xyz.h"

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

===============>>#19 票数:7

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

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

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

===============>>#20 票数:6

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

===============>>#21 票数:6

表格 1 - #include <xxx>

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

表格 2 - #include "xxx"

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


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

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


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

===============>>#22 票数:5

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

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

===============>>#23 票数:5

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

而“文件名”也在当前目录中搜索。

理想情况下,您应该将 <...> 用于标准 C 库,而将“...”用于您编写并存在于当前目录中的库。

===============>>#24 票数:5

#include <filename>

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

#include "filename"

  • 这告诉编译器搜索程序正在运行的头文件。 如果失败,它的行为类似于#include <filename>并在系统头文件存储的位置搜索该头文件。
  • 这种方法通常用于识别用户定义的头文件(由用户创建的头文件)。 如果您想调用标准库,请不要使用它,因为它比#include <filename>花费更多的编译时间。

===============>>#25 票数:4

#include <filename>

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

#include "path-to-file/filename"

当您想使用您自己的项目文件夹或其他地方的自定义头文件时使用。

有关预处理器和标头的更多信息。 阅读C 预处理器

===============>>#26 票数:3

要使用 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=deprecated-objc-isa-usage -E -disable-free -禁用-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-diagnostics -traditional-cpp -o - -xc /dev/null
clang -cc1 version 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 票数:2

一般来说,区别在于预处理器搜索头文件的位置:

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

  1. #include <filename>用于在程序中包含系统库头文件,表示C/C++预处理器将搜索C库文件所在的文件名或预定义的系统头文件所在的文件名。
  2. #include "filename"用于在程序中包含用户定义的头文件,表示 C/C++ 预处理器将在程序所在的当前目录中搜索文件名,然后按照 #include <filename> 使用的搜索路径进行搜索

检查 gcc 文档gcc 包含文件

===============>>#28 票数:1

#include <file> 

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

#include "file" 

在编译它的当前目录中包含一个文件。

===============>>#29 票数:1

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

gcc -v -o a a.c

以下是一些使事情更清楚的示例:代码 ac 有效

// a.c
#include "stdio.h"
int main() {
        int a = 3;
        printf("a = %d\n", a);
        return 0;

}

bc 的代码也有效

// 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;
}

ac会产生编译错误,但bc仍然有效

和 "", <> 可以与相同的文件名一起使用。 因为搜索路径优先级不同。 所以dc也能用

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

        a = foo();

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

        return 0;
}

===============>>#30 票数:1

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

所以

#include <myFilename>

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

#include "myFilename"

===============>>#31 票数:-3

#include <filename>     (1)     
#include "filename"     (2)

#include将由文件名标识的源文件包含在指令后紧接的行中的当前源文件中。

该指令的第一个版本仅搜索标准包含目录。 标准C ++库以及标准C库隐式包含在标准包含目录中。 用户可以通过编译器选项控制标准的包含目录。

第二个版本首先搜索当前文件所在的目录,并且只有在找不到该文件的情况下,才搜索标准包含目录。

在找不到文件的情况下,程序格式错误。

===============>>#32 票数:-3

在 C 和 C++ 编程语言中,在include语句中使用尖括号和使用引号有什么区别,如下所示?

  1. #include <filename>
  2. #include "filename"

  ask by quest49 translate from so

未解决问题?本站智能推荐: