关于C++:#include 和#include “filename”包含文件的区别

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

在C和C++编程语言中,在EDOCX1×0语句中使用角括号和引用的区别是什么?

  • #include
  • #include"filename"

  • 实际上,不同之处在于预处理器在其中搜索包含的文件的位置。

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

    对于#include"filename",预处理器首先在包含该指令的文件所在的目录中进行搜索,然后按照用于#include 表单的搜索路径进行搜索。此方法通常用于包括程序员定义的头文件。

    在搜索路径的GCC文档中可以找到更完整的描述。


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

    在C标准第6.10.2节第2至4段中,规定:

    • A preprocessing directive of the form

      1
      #include <h-char-sequence> new-line

      searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

    • A preprocessing directive of the form

      1
      #include"q-char-sequence" new-line

      causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

      1
      #include <h-char-sequence> new-line

      with the identical contained sequence (including > characters, if any) from the original
      directive.

    • A preprocessing directive of the form

      1
      #include pp-tokens new-line

      (that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.

    Definitions:

    • h-char: any member of the source character set except the new-line character and >

    • q-char: any member of the source character set except the new-line character and "


    <和>之间的字符序列唯一地引用了一个头文件,它不一定是一个文件。实现可以随意使用字符序列。(不过,大多数情况下,只需将其视为文件名,并在include路径中进行搜索,就像其他posts状态一样。)

    如果使用#include"file"表单,则实现首先查找给定名称的文件(如果支持)。如果没有(支持),或者搜索失败,那么实现的行为就像使用了另一个(#include 表单)。

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


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

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

    -I directory

    Change the algorithm for searching for headers whose names are not absolute pathnames to look in the directory named by the directory pathname before looking in the usual places. Thus, headers whose names are enclosed in double-quotes ("" ) shall be searched for first in the directory of the file with the #include line, then in directories named in -I options, and last in the usual places. For headers whose names are enclosed in angle brackets ("<>" ), the header shall be searched for only in directories named in -I options and then in the usual places. Directories named in -I options shall be searched in the order specified. Implementations shall support at least ten instances of this option in a single c99 command invocation.

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


    GCC文件对两者的区别作了如下说明:

    Both user and system header files are included using the preprocessing directive ‘#include’. It has two variants:

    #include

    This variant is used for system header files. It searches for a file named file in a standard list of system directories. You can prepend directories to this list with the -I option (see Invocation).

    #include"file"

    This variant is used for header files of your own program. It searches for a file named file first in the directory containing the current file, then in the quote directories and then the same directories used for . You can prepend directories to the list of quote directories with the -iquote option.
    The argument of ‘#include’, whether delimited with quote marks or angle brackets, behaves like a string constant in that comments are not recognized, and macro names are not expanded. Thus, #include specifies inclusion of a system header file named x/*y.

    However, if backslashes occur within file, they are considered ordinary text characters, not escape characters. None of the character escape sequences appropriate to string constants in C are processed. Thus,#include"x
    \\y"
    specifies a filename containing three backslashes. (Some systems interpret ‘\’ as a pathname separator. All of these also interpret ‘/’ the same way. It is most portable to use only ‘/’.)

    It is an error if there is anything (other than comments) on the line after the file name.

    < /块引用>


    确实如此:

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

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

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

    如果./中,那么没有什么区别。

    如果mypath/myfile在另一个include目录中,则行为未定义。


    include通知预处理器先在-I目录和预定义目录中搜索,然后在.c文件的目录中搜索。"file"include通知预处理器首先搜索源文件的目录,然后恢复到-I和预定义目录。搜索所有目的地,但搜索顺序不同。

    2011年标准主要讨论"16.2源文件包含"中的包含文件。

    2 A preprocessing directive of the form

    # include new-line

    searches a sequence of implementation-defined places for a header identified uniquely by the
    specified sequence between the < and > delimiters, and causes the
    replacement of that directive by the entire contents of the header.
    How the places are specified or the header identified is
    implementation-defined.

    3 A preprocessing directive of the form

    # include"q-char-sequence" new-line

    causes the replacement of that directive by the entire contents of the source file identified by the
    specified sequence between the" delimiters. The named source file is
    searched for in an implementation-defined manner. If this search is
    not supported, or if the search fails, the directive is reprocessed as
    if it read

    # include new-line

    with the identical contained sequence (including > characters, if any) from the original directive.

    注意,如果找不到文件,"xxx"格式将降级为格式。其余的是实现定义的。


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

    • A preprocessing directive of the form

      1
      #include <h-char-sequence> new-line

      searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

    • A preprocessing directive of the form

      1
      #include"q-char-sequence" new-line

      causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

      1
      #include <h-char-sequence> new-line

      with the identical contained sequence (including > characters, if any) from the original
      directive.

    • A preprocessing directive of the form

      1
      #include pp-tokens new-line

      (that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.

    Definitions:

    • h-char: any member of the source character set except the new-line character and >

    • q-char: any member of the source character set except the new-line character and "

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

    正式来说,您必须阅读编译器的手册,但是通常(传统上)#include"..."表单搜索首先找到#include的文件的目录,然后搜索#include <...>表单搜索的目录(包括路径,如系统头)。


    感谢你的回答,特别是亚当·斯泰马斯茨基、皮科基和艾布。

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

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

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

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

    如果您真的担心这个问题,请使用"./myHeader.h"作为源代码所在目录中的include文件(我当前的非常大的项目中有一些重复的include文件名,这些文件名分散在各处——实际上是一个配置管理问题)。

    这是为了您的方便而复制的MSDN解释)。

    Quoted form

    The preprocessor searches for include files in this order:

  • In the same directory as the file that contains the #include statement.
  • In the directories of the currently opened include files, in the reverse order in which
    they were opened. The search begins in the directory of the parent include file and
    continues upward through the directories of any grandparent include files.
  • Along the path that's specified by each /I compiler option.
  • Along the paths that are specified by the INCLUDE environment variable.
  • Angle-bracket form

    The preprocessor searches for include files in this order:

  • Along the path that's specified by each /I compiler option.
  • When compiling occurs on the command line, along the paths that are specified by the INCLUDE environment variable.

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

    因此,如果您想要生成依赖性规则(例如使用gcc-m选项),您必须对应该包含在依赖性树中的文件使用带引号的表单。

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


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


    #include 通知编译器在其"include"目录中搜索头文件,例如,对于mingw,编译器将在c:mingwinclude中或安装编译器的任何位置搜索file.h

    #include"file"通知编译器搜索当前目录(即源文件所在的目录)以查找file

    您可以使用gcc的-I标志告诉它,当遇到带尖括号的include时,它还应该在-I之后在目录中搜索头。gcc将在标记后处理目录,就好像它是includes目录一样。

    例如,如果您在自己的目录中有一个名为myheader.h的文件,那么如果您使用-I .标志调用gcc(表示它应该搜索当前目录中的includes),则可以称为#include

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


    当你使用包含<文件名>的预处理器时,在C + C++头文件目录中查找文件(STdio.HCSTDIO、字符串、向量等)。但是,当你使用包含"文件名"时:首先,预处理器在当前目录中查找文件,如果它不在这里,他在C+C++头文件的目录中寻找它。


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

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

    1
    #include <iostream>
    • #include""是程序员定义的头文件。

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

    1
    #include"myfile.h"


    带尖括号的include将搜索"依赖于实现的位置列表"(这是一种非常复杂的表示"系统标题"的方式),以包含文件。

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

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

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


    1
    2
    #include"filename" // User defined header
    #include <filename> // Standard library header.

    例子:

    这里的文件名是Seller.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #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的文件中),现在应该包括用户定义的头,如下所示:

    1
    #include"Seller.h"

    这里的许多答案都集中在编译器将搜索以查找文件的路径上。虽然这是大多数编译器所做的,但一致的编译器可以使用标准头文件的效果进行预编程,并将#include 视为一个开关,它根本不需要作为一个文件存在。

    这不是纯粹的假设。至少有一个编译器是这样工作的。建议仅使用带标准头的#include


    1
    #include

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

    1
    #include"xyz.h"

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


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

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

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


    the" < filename >" searches in standard C library locations

    whereas"filename" searches in the current directory as well.

    理想情况下,您将使用<…>表示标准C库,而"…"表示您编写并存在于当前目录中的库。


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


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

    1.9-头文件更详细地解释了预处理器指令。如果你是一个新手程序员,那么这个页面应该能帮助你理解所有这些。我是从这里学来的,在工作中我一直在跟踪它。


    #include

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

    #include"path-to-file/filename"

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

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


    表格1-包括"XXX"

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

    表2-include

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

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

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

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


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

    cpp -v /dev/null -o /dev/null

    Apple LLVM version 10.0.0 (clang-1000.10.44.2)
    Target: x86_64-apple-darwin18.0.0
    Thread model: 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-diagnostics -traditional-cpp -o - -x c /dev/null
    clang -cc1 version 10.0.0 (clang-1000.10.44.2) default target x86_64-apple-darwin18.0.0 ignoring
    nonexistent directory"/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include"
    ignoring nonexistent directory"/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
    #include"..." search starts here:
    #include <...> search starts here:
    /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)
    End of search list.


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

    #include包含源文件,由文件名标识,在指令后的第二行将其放入当前源文件中。

    The first version of the directive searches only standard include
    directories. The standard C++ library, as well as standard C library,
    is implicitly included in standard include directories. The standard
    include directories can be controlled by the user through compiler
    options.

    The second version first searches the directory where the current file
    resides and, only if the file is not found, searches the standard
    include directories.

    如果找不到文件,则说明程序格式错误。


    写include语句有两种方法,它们是:

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

    每种形式的含义是

    1
    #include"mylib.h"

    此命令将在当前目录中查找文件mylib.h,以及指定的目录列表(如include搜索路径中所述),这些目录可能已设置。

    1
    #include<mylib.h>

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

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


    #include

    将从C++库中找到相应的文件。这意味着如果在C++库文件夹中有一个名为Hello .h的文件,EDCOX1 OR 12将加载它。

    但是,

    #include"filename"

    将在源文件所在的目录中找到该文件。

    此外,

    #include"path_to_file/filename"

    将在您在path_to_file中键入的目录中找到该文件。


    我相信,如果在当前目录中找不到双引号中包含的头文件,那么将在与尖括号包含的头文件相同的系统路径中查找它们。


    搜索头文件的顺序不同。首选先搜索标准头,而"xxx.h"则先搜索工作区的头文件。


    为了包含一个预定义的库头文件,使用#include,而包括用户定义的头文件,#include"filename"是相关的。