命名空间
变体
操作

源文件包含

来自 cppreference.com

将另一个源文件包含到当前源文件中,位于指令后的下一行。

内容

[编辑] 语法

#include < h-char-sequence > new-line (1)
#include " q-char-sequence " new-line (2)
#include pp-tokens new-line (3)
__has_include ( " q-char-sequence " )
__has_include ( < h-char-sequence > )
(4) (自 C23 起)
__has_include ( string-literal )
__has_include ( < h-pp-tokens > )
(5) (自 C23 起)
1) 搜索由 h-char-sequence 唯一标识的头文件,并将指令替换为头文件的全部内容。
2) 搜索由 q-char-sequence 标识的源文件,并将指令替换为源文件的全部内容。它可能会回退到 (1) 并将 q-char-sequence 视为头文件标识符。
3) 如果 (1)(2) 都未匹配,则 pp-tokens 将进行宏替换。替换后的指令将再次尝试匹配 (1)(2)
4) 检查是否有可供包含的头文件或源文件。
5) 如果 (4) 未匹配,则 h-pp-tokens 将进行宏替换。替换后的指令将再次尝试匹配 (4)
new-line - 换行符
h-char-sequence - 一个或多个 h-char 的序列,其中出现以下任何字符会导致未定义的行为
  • 字符 '
  • 字符 "
  • 字符 \
  • 字符序列 //
  • 字符序列 /*
h-char - 源字符集 中的任何成员,除了换行符和 >
q-char-sequence - 一个或多个 q-char 的序列,其中出现以下任何字符会导致未定义的行为
  • 字符 '
  • 字符 \
  • 字符序列 //
  • 字符序列 /*
q-char - 源字符集 中的任何成员,除了换行符和 "
pp-tokens - 一个或多个 预处理标记 的序列
string-literal - 一个 字符串文字
h-pp-tokens - 一个或多个 预处理标记 的序列,除了 >

[编辑] 解释

1) 以实现定义的方式搜索由 h-char-sequence 标识的文件。此语法的目的是搜索实现控制下的文件。典型的实现只搜索标准包含目录。标准 C 库隐式地包含在这些标准包含目录中。标准包含目录通常可以通过编译器选项由用户控制。
2) 以实现定义的方式搜索由 q-char-sequence 标识的文件。此语法的目的是搜索不受实现控制的文件。典型的实现首先搜索当前文件所在的目录,并且仅在找不到文件时,才会像 (1) 那样搜索标准包含目录。
3) 指令中 include 后面的预处理标记与普通文本中的处理方式相同(即,当前定义为宏名称的每个标识符都将替换为其预处理标记的替换列表)。所有替换完成后,生成的指令应与之前两种形式之一匹配。将 <> 预处理标记对或一对 " 字符之间的预处理标记序列组合成单个头文件名预处理标记的方法是实现定义的。
4)h-char-sequenceq-char-sequence 标识的头文件或源文件将被搜索,就好像该预处理标记序列是 (3) 语法中的 pp-tokens 一样,除了不进行进一步的宏扩展。如果这样的指令不满足 #include 指令的语法要求,则程序格式不正确。如果源文件搜索成功,则 __has_include 表达式计算为 1,如果搜索失败,则计算为 0
5) 仅当 (4) 语法不匹配时才会考虑此形式,在这种情况下,预处理标记将与普通文本中的处理方式相同。

如果找不到文件,则程序格式不正确。

__has_include 可以在 #if #elif 的表达式中扩展。它被 #ifdef #ifndef #elifdef #elifndefdefined 视为已定义的宏,但不能在其他任何地方使用。

(自 C23 起)

[编辑] 注释

典型的实现只搜索标准包含目录以用于语法 (1)。标准 C 库隐式地包含在这些标准包含目录中。标准包含目录通常可以通过编译器选项由用户控制。

语法 (2) 的目的是搜索不受实现控制的文件。典型的实现首先搜索当前文件所在的目录,然后回退到 (1)

当包含文件时,它将通过 翻译阶段 1-4 进行处理,这可能包括递归地扩展嵌套的 #include 指令,直到达到实现定义的嵌套限制。为了避免重复包含同一个文件以及当文件包含自身(可能是间接地)时出现无限递归,通常使用 _头文件保护_:整个头文件都包装在

#ifndef FOO_H_INCLUDED /* any name uniquely mapped to file name */
#define FOO_H_INCLUDED
// contents of the file are here
#endif

许多编译器还实现了非标准的 pragma #pragma once,它具有类似的效果:如果同一个文件(其中文件标识以特定于操作系统的方式确定)已经被包含,它将禁用该文件的处理。

__has_include 的结果为 1 仅表示存在具有指定名称的头文件或源文件。它并不意味着头文件或源文件在包含后不会导致错误或包含任何有用的内容。

[编辑] 示例

[编辑] 参考文献

  • C23 标准 (ISO/IEC 9899:2024)
  • 6.4.7 头文件名 (p: 69)
  • 6.10.1 条件包含 (p: 165-169)
  • 6.10.2 源文件包含 (p: 169-170)
  • C17 标准 (ISO/IEC 9899:2018)
  • 6.10.2 源文件包含 (p: 119-120)
  • C11 标准 (ISO/IEC 9899:2011)
  • 6.10.2 源文件包含 (p: 164-166)
  • C99 标准 (ISO/IEC 9899:1999)
  • 6.10.2 源文件包含 (p: 149-151)
  • C89/C90 标准 (ISO/IEC 9899:1990)
  • 3.8.2 源文件包含

[编辑] 另请参阅

C 标准库头文件的列表
C++ 文档 对于 源文件包含