Namespaces
Variants

Source file inclusion

From cppreference.net

在当前源文件中紧接指令行之后包含另一个源文件。

目录

语法

#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-sequence q-char-sequence 标识的头文件或源文件,将按照该预处理标记序列作为语法 (3) pp-tokens 的方式进行搜索,但不再进行进一步的宏展开。若此类指令不满足 #include 指令的语法要求,则程序非良构。当源文件搜索成功时, __has_include 表达式求值为 1 ;搜索失败时则求值为 0
5) 仅当语法 (4) 不匹配时才会考虑此形式,此时预处理标记的处理方式与普通文本完全相同。

若文件未找到,则程序格式不正确。

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

(自 C23 起)

注释

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

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

当文件被包含时,它会经过 翻译阶段 1-4 的处理,这可能递归地包含嵌套 #include 指令的展开,直至达到实现定义的嵌套限制。为避免同一文件的重复包含及文件(可能通过传递方式)包含自身时产生的无限递归,通常采用 头文件保护 机制:将整个头文件包裹在

#ifndef FOO_H_INCLUDED /* 任何与文件名唯一映射的名称 */
#define FOO_H_INCLUDED
// 文件内容在此处
#endif

许多编译器还实现了非标准的 pragma #pragma once 具有类似效果:当同一文件(通过操作系统特定的方式确定文件标识)已被包含时,该指令会禁用对该文件的重复处理。

__has_include 的结果为 1 时,仅表示存在指定名称的头文件或源文件。这并不代表包含该头文件或源文件时不会引发错误,也不保证其包含任何有效内容。

示例

参考文献

  • C23 标准 (ISO/IEC 9899:2024):
  • 6.4.7 头文件名 (页: 69)
  • 6.10.1 条件包含 (页: 165-169)
  • 6.10.2 源文件包含 (页: 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 源文件包含(页码:149-151)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 3.8.2 源文件包含

参见

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