一、 编译
1. 预编译
将相关的头文件预编译成一个.i文件;
预编译主要处理源代码文件中的以 “#” 开始的预编译命令,如“#include”, "#define"等
主要处理规则:
- 将所有的#define 删除,并展开所有的宏定义。
- 处理所有的条件预编译指令,“#ifdef”等
- 处理“#include”, 将被包含的文件插入到该预编译指令的位置,递归进行,如果被包含的文件包含其他文件,继续展开
- 删除注释
- 添加行号,文件名标识, 方便编译产生错误时打印行号
- 保留#pragma编译器指令
2. 编译
对预处理后的文件进行一系列的词法分析,语法分析,语义分析,优化后的汇编代码文件
1)词法分析
将程序进行扫描,运用类似于有限状态机的算法将源代码的字符进行分割
分割产生的记号一般分为:关键字,标识符,变量,符号等
识别记号的同时将对应的记号放到对用的表,方便之后的步骤使用
2)语法分析
对扫描出来的记号进行语法分析,生成语法树
整个分析过程使用了上下文无关语法的分析手段
由语法分析器生成的语法树,就是以表达式为节点的树
array[index] = (index + 4) * (2 + 6)
如果表达式不合法,在语法分析阶段就会报错
3)语义分析
语义分为静态语义和动态语义
静态语义是在编译阶段可以确定的语义,如赋值的类型不匹配
动态语义是在运行阶段可以确定的 ,比如除数为0
在语义分析时对整个的语法树的表达式进行标识类型,如上述语法树会标识整型数组,整形