(C语言) 8大翻译阶段

(C语言) 8大翻译阶段

文章目录

  • [(C语言) 8大翻译阶段](#(C语言) 8大翻译阶段)
    • ⭐前言
    • 🗃️8大阶段
      • [🗂️1. 字符映射](#🗂️1. 字符映射)
      • [🗂️2. 行分割](#🗂️2. 行分割)
      • [🗂️3. 标记化](#🗂️3. 标记化)
      • [🗂️4. 预处理](#🗂️4. 预处理)
      • [🗂️5. 字符集映射](#🗂️5. 字符集映射)
      • [🗂️6. 字符串拼接](#🗂️6. 字符串拼接)
      • [🗂️7. 翻译](#🗂️7. 翻译)
      • [🗂️8. 链接](#🗂️8. 链接)
    • [🗃️C++ 的 9 大阶段](#🗃️C++ 的 9 大阶段)
    • ⭐END

⭐前言

我们常说的C语言编译的4阶段,预处理,汇编,编译,链接

其实这背后有复杂和细分的阶段,将之称为翻译阶段。

而C语言共有8个这样的阶段。

  1. 字符映射
  2. 行分割
  3. 标记化
  4. 预处理
  5. 字符集映射
  6. 字符串拼接
  7. 翻译
  8. 链接

🗃️8大阶段

🗂️1. 字符映射

编译器将物理源文件中的字符转换为编译器可以理解的内部表示。

这通常涉及到字符编码的处理,比如将文件中的UTF-8UTF-16等编码字符统一转换为编译器可识别的源字符集字符集。

注意:在 C23 前需要处理三标符

源字符集 是包含作为单字节子集的基本源字符集的多字节字符集,后者由以下 96 个字符组成:

a) 5 个空白字符(空格、水平制表、垂直制表、换页、换行)

b) 10 个数字字符,从 '0' 到 '9'

c) 52 个字母,从 'A' 到 'Z' 以及从 'a' 到 'z'

d) 29 个标点字符: _ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '

🗂️2. 行分割

编译器将物理行转化为逻辑行。

将代码并按行分割,这样每行可以单独进行处理。

在源代码中由反斜杠\结尾(紧跟着换行符),删除反斜杠和换行符号,将下一个物理行连接上来合并为一个逻辑行。

注意:若此步骤后,非空源文件不以换行符结束(无论是原本就无换行,还是以反斜杠结束),则行为未定义。

物理行 (physical line) -> 逻辑行 (logical line)

物理文件

c 复制代码
#include <stdio.h>
 
#define PUTS p\
u\
t\
s
/* 行拼接在阶段 2 进行,
 * 而宏的标记分析是在阶段 3 并在阶段 4 展开,
 * 因此以上代码等价于 #define PUTS puts
 */
 
int main(void)
{
 /* 用行拼接来调用 puts */ PUT\
S\
("Output ends here\\
0Not printed" /* 行拼接之后,剩余的反斜杠
               * 转义了 0,提早结束了字符串。
               */
);
}

效果

c 复制代码
#include <stdio.h>

#define PUTS puts

int main(void)
{
                                  PUTS

 ("Output ends here\0Not printed"



);
}

🗂️3. 标记化

编译器将源代码分解最小独立单元。

将源文件分解为注释、空白字符(空格、水平制表、换行、垂直制表、换页)序列和下列预处理记号

​ a) 头文件名:<stdio.h>"myfile.h"

​ b) 标识符

​ c) 预处理数字,包括整数常量浮点常量,但也包括一些非法记号,例如 1...E+3.foo 或 0JBK

​ d) 字符常量字符串字面量

​ e) 运算符与标点,例如 +、<<=、<% 或 ##。

​ f) 不属于任何其他类别的单独非空白字符

以一个空格字符替换每段注释

保持换行符。是否可将非换行的空白符序列缩减成单个空格字符是实现定义的。

另一种分类法:

Tokens:

The smallest individual units are known as tokens such as keywords, identifiers, strings, operators &

special symbols.

  1. Keywords are the reserved (special) words and can't be used as variable, functions names.
  2. Identifiers refer to the names of the variables, arrays, functions, classes etc.
  3. Constants refer to fixed values that we cannot change in a program.
  4. String is a group of characters.
  5. Operators are special symbols which operate on variable & constants and form expressions.
  6. Special symbols are () {} [] etc.

🗂️4. 预处理

预处理器对上述的结果进行预处理。

执行预处理器

#include 指令所引入的每个文件都经历阶段 1 到 4(上述所有阶段),递归执行。

此阶段结束时,从源码移除所有预处理器指令。

🗂️5. 字符集映射

将源字符集转换成执行字符集。

字符常量字符串字面量中的所有字符及转义序列源字符集 转换成执行字符集 (可为如 UTF-8 的多字节字符集,只要来自阶段 1 中所列的基本源字符集的所有 96 个字符拥有单字节表示)。

注意:若转义序列所指定的字符不是执行字符集的成员,则结果是实现定义的,但保证不是空(宽)字符。

🗂️6. 字符串拼接

连接相邻的字符串字面量

例如,使用字符串化运算符(#)可以将两个字符串合并。

c 复制代码
#include <stdio.h>

int main() {
    const char* str = "Hello" ", " "World";
    printf(str);
}

最后将输出:Hello, World

🗂️7. 翻译

对每个翻译单元进行翻译。

发生编译:对各个记号进行语法和语义分析,并将它们作为翻译单元完成翻译。

这个阶段将预处理后的源代码转换成中间表示形式,然后进一步转换成目标代码。

这包括语法分析、语义分析、中间代码生成、代码优化和目标代码生成。

🗂️8. 链接

将所有需要的二进制文件连接成一个可执行程序。

发生链接:将翻译单元和满足外部引用所需的库组件到汇集成程序映像,它含有在其执行环境(操作系统)中执行所需的信息。

🗃️C++ 的 9 大阶段

C++ 共 9 个阶段,本质和 C语言 差不多,有一些细节的差异。

最核心的是在翻译和链接之间 ,有一个实例化模板阶段。

🗂️实例化模板

检验每个翻译单元,产生所要求的模板实例化的列表,其中包括显式实例化所要求的实例化。

定位模板定义,并进行所要求的实例化,以产生实例化单元




⭐END

🌟ref

C 翻译阶段 - cppreference.com

C++ 翻译阶段 - cppreference.com

Effective C 中文版 (豆瓣)

🌟交流方式

关注我,学习更多C/C++,python,算法,软件工程,计算机知识!

⭐交流方式⭐ |C/C++|算法|设计模式|软件架构-CSDN社区
B站

👨‍💻主页:天赐细莲 bilibili

相关推荐
❥ღ Komo·37 分钟前
K8s1.28.15网络插件Calico全解析
开发语言·php
❥ღ Komo·40 分钟前
K8s服务发现与DNS解析全解析
java·开发语言
FuckPatience42 分钟前
C# 项目调试的时候进不去断点
开发语言·c#
元亓亓亓43 分钟前
考研408--组成原理--day8--汇编指令&不同语句的机器级表示
开发语言·汇编·c#
醇氧7 小时前
【Windows】优雅启动:解析一个 Java 服务的后台启动脚本
java·开发语言·windows
hetao17338378 小时前
2025-12-12~14 hetao1733837的刷题笔记
数据结构·c++·笔记·算法
椰子今天很可爱8 小时前
五种I/O模型与多路转接
linux·c语言·c++
MapGIS技术支持8 小时前
MapGIS Objects Java计算一个三维点到平面的距离
java·开发语言·平面·制图·mapgis
程序员zgh8 小时前
C++ 互斥锁、读写锁、原子操作、条件变量
c语言·开发语言·jvm·c++
小灰灰搞电子9 小时前
Qt 重写QRadioButton实现动态radioButton源码分享
开发语言·qt·命令模式