编译和链接
C语言的编译过程
预编译
gcc -E hello.c -o hello.i
g++ hello.c > hello.i
预编译过程主要处理#开头的预编译指令。
处理规则:
- 删除所有#define,并展开所有的宏定义
- 处理所有条件预编译指令
- 处理#include预编译指令,并将被包含的文件插入到该预编译指令的位置
- 删除所有注释//和/*
- 添加行号和文件名标志
- 保留所有的#pragma编译器指令
编译
编译指把预处理完的文件进行一系列的词法分析,语法分析,语义分析和优化后生成相应的汇编代码。
gcc -S hello.i -o hello.s
汇编
将汇编代码转变成机器可以执行的代码。
as hello.s -o hello.o
或者 gcc -c hello.s -o hello.o
链接
编译过程
分为扫描,语法分析,语义分析,源代码优化,代码生成和目标代码优化。
语法分析
将源代码输入到扫描器中,生成一系列的token。
语法分析
对token进行语法分析,生成语法分析树,整个过程采用上下文无关语法。
语义分析
完成了对表达式的语法层面的分析,编译期所能进行的语义分析是静态语义,动态语义只能在运行期才能完成。
静态语义包括声明和类型的匹配,类型的转换。
中间语言生成
中间代码使得编译器分为前端和后端,前端负责产生机器无关的中间代码,编译器后端将中间代码转换成目标机器代码。
目标代码生成与优化
后端主要包括代码生成器和目标代码优化器。
代码生成器将中间代码转换成目标机器代码。
目标代码优化器对目标代码进行优化。
链接
重新计算各个目标地址过程被叫做重定位。
符号用来表示一个地址。
静态链接
将程序组装起来的过程就是链接。链接主要是把各个模块之间相互引用的部分处理好,使得各个模块之间能够被正确衔接。
链接过程主要包括地址和空间分配,符号绑定,重定位。