GCC编译C文件时,会进行:预处理、编译、汇编及链接
预处理
预处理阶段将会把源文件中预编译指令进行处理,如将会把宏全部展开。该部分工作由预处理器完成。
gcc -E hello.c -o hello.i
将会输出预处理的结果。
编译
编译将会把预处理后的语言,转换成机器语言(汇编)。由编译器进行。按照顺序会进行词法分析、语法分析、语义分析、中间语言生成、目标语言生成及优化。
- 词法分析
将源代码进行扫描,运用有限状态机的算法将源代码分割成一系列的记号。记号可分为:关键字、标识符、字面量(数字、字符串)和特殊符号(如运算符)。
- 语法分析
由语法分析器完成,使用到上下文无关语法。将词法分析产生的记号进行语法分析,生成以表达式为节点的语法树。
- 语义分析
将会对表达式是否有意义进行判断。编译器所进行的语义分析是静态的。如,可以判断1/0
的错误,但是对1/sum;sum=0;
则无法判断。该部分开始检查语法。
- 中间语言生成
将语法分析产生的带有类型标记的语法树转换成更加简单的表达式,如三地址表达式x=y op z
。目的是能够方便的转换成汇编码。在转换成三地之表达式之后,会进行优化,计算出静态的结果。如sum=2+6
会转换成sum=8
。诸如此类。
- 目标代码生成和优化
将三地址表达式转换成汇编语言并进行优化。
至此,结果文件和操作系统具体的硬件结构(变量长度等)仍然无关。
汇编
将编译后的汇编语言转换成二进制机器码。汇编后的文件将不能跨操作系统运行(一般操作系统文件格式不一样)。
链接
根据文件之间的引用关系,对二进制文件进行链接,并汇总成目标文件。此处链接应该只进行静态链接。链接过程会进行 地址和空间重分配、符号决议和重定位(不同文件汇总时的调整)。
如果文件间的包含关系出现问题(如头文件的重复包含),会于此处报错。
- 文件依赖的避免
- 链接时动态库的加载