在我们平常的应用程序开发的过程中,我们很少去关注编译和链接的过程,因为通常的开发环境都是集成的开发环境(IDE)
首先,我们编写一个"hello word”的程序如下:
在Linux下,当我们使用gcc来编译程序如下:
实际上,上述过程,我们可以将其分为4个步骤
分别是预处理、编译、汇编和链接
1、预编译
对上述程序进行预编译,生成一个.i文件
预编译主要处理那些源代码文件中以“#”开始的预编译指令,比如“#define”、“#include”,主要处理规则如下:
- 将所有的“#define”删除,并且展开所有的宏定义
- 处理所有的条件预编译指令,比如“#if”、“#ifdef”、“endif”
- 处理“#include”预编译指令,这个过程是一个递归的过程,因为被包含的文件可能还包含其他文件
- 删除所有的注释
- 添加行号和文件名标识以便于编译时编译器调试产生行号信息和错误或警告时显示行号信息
- 保留所有的#pragma编译器指令因为编译器要使用他们,预编译器无法处理
综上,可以看出,当我们无法判断宏定义是否正确或头文件包含是否正确时,可以查看预编译后的文件来确定问题
2、编译
编译过程如下:生成的.s文件
补充:现在gcc把预编译和编译两个过程合并成了一个步骤,使用一个叫做ccl的程序完成。
主要进行步骤分为6步:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化。
以程序 array[index] = (index + 4) *(2+6)为例子,加以分析:
2.1 词法分析:
首先源代码程序被输入到扫描器,进行词法分析,运用类似于邮箱状态机的算法将原地代码的字符序列分割成一系列的记号。