翻译阶段
来自cppreference.com
编译器如同下列阶段以此准确顺序发生一般处理 C 源文件。实际实现可以组合,或以不同方式处理这些动作,只要行为相同。
阶段 1
1) 以实现定义方式,映射源文件(通常是以某种多字节,例如 UTF-8 编码的文本文件)的单独字节,为源字符集的字符。特别是以换行字符替换依赖 OS 的行尾指示符。
- 源字符集是包含作为单字节子集的基本源字符集的多字节字符集,后者由以下 96 个字符组成:
a) 5 个空白字符(空格、水平制表、垂直制表、换页、换行)
b) 10 个数字字符,从 '0' 到 '9'
c) 52 个字母,从 'A' 到 'Z' 以及从 'a' 到 'z'
d) 29 个标点字符: _ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '
2) 以对应的单字节表示替换三标符。
阶段 2
1) 凡在反斜杠出现于行尾(立即为换行符所后随)时,删除反斜杠和换行符,把二个物理源码行组合成一个逻辑源码行。这是单趟操作:以二个反斜杠结束,后随一个空行的行不会把三行组合为一。
2) 若此步骤后,非空源文件不以换行符结束(无论是原本就无换行,还是以反斜杠结束),则行为未定义。
阶段 3
1) 将源文件分解为注释、空白字符(空格、水平制表、换行、垂直制表、换页)序列和下列预处理记号:
a) 头文件名: <stdio.h> 或 "myfile.h"
b) 标识符
e) 运算符与标点,例如 + 、 <<= 、 <% 或 ## 。
f) 不属于任何其他类别的单独非空白字符
2) 以一个空格字符替换每段注释
3) 保持换行符。是否可将非换行的空白符序列缩减成单个空格字符是实现定义的。
若已经分析输入为到给定字符为止的预处理记号,则通常将能构成一个预处理记号的最长字符序列处理成下个预处理记号,即这会导致后继分析失败。这常被称为最大吞噬 (maximal munch) 。
int foo = 1; int bar = 0xE+foo; // 错误:非法的预处理数字 0xE+foo int baz = 0xE + foo; // OK int quux = bar+++++baz; // 错误: bar++ ++ +baz ,而非 bar++ + ++baz 。
最大吞噬规则的单独例外是:
- 头文件名预处理记号仅在
#include
指令中和#pragma
指令中的实现定义位置形成。
#define MACRO_1 1 #define MACRO_2 2 #define MACRO_3 3 #define MACRO_EXPR (MACRO_1 <MACRO_2> MACRO_3) // OK : <MACRO_2> 不是头文件名
阶段 4
1) 执行预处理器。
2) #include 指令所引入的每个文件都经历阶段 1 到 4 ,递归执行。
3) 此阶段结束时,从源码移除所有预处理器指令。
阶段 5
1) 将字符常量及字符串字面量中的所有字符及转义序列从源字符集转换成执行字符集(可为如 UTF-8 的多字节字符集,只要来自阶段 1 中所列的基本源字符集的所有 96 个字符拥有单字节表示)。若转义序列所指定的字符不是执行字符集的成员,则结果是实现定义的,但保证不是空(宽)字符。
注意:某些实现中,能以命令行选项控制此阶段所进行的转换: gcc 和 clang 用 -finput-charset 指定源字符集的编码,用 -fexec-charset 和 -fwide-exec-charset 指定无编码前缀的 (C11 起)字符串字面量和字符常量中的执行字符集的编码。
阶段 6
连接相邻的字符串字面量。
阶段 7
发生编译:按照语法和语义分析记号,并将它们翻译成翻译单元。
阶段 8
发生链接:将翻译单元和满足外部引用所需的库组件到汇集成程序映像,它含有在其执行环境(操作系统)中执行所需的信息。
引用
- C11 标准(ISO/IEC 9899:2011):
- 5.1.1.2 Translation phases (第 10-11 页)
- 5.2.1 Character sets (第 22-24 页)
- 6.4 Lexical elements (第 57-75 页)
- C99 标准(ISO/IEC 9899:1999):
- 5.1.1.2 Translation phases (第 9-10 页)
- 5.2.1 Character sets (第 17-19 页)
- 6.4 Lexical elements (第 49-66 页)
- C89/C90 标准(ISO/IEC 9899:1990):
- 2.1.1.2 Translation phases
- 2.2.1 Character sets
- 3.1 Lexical elements