在ANSI C的任意一种实现中,存在两个不同的环境
- 翻译环境,在该环境中源代码被转换为可执行的机器指令
- 执行环境,它用于实际执行代码
组成一个程序的每个源文件通过编译过程分别转换成目标代码,每个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序。
1.预编译阶段
在gcc环境下,一个.c文件经过预编译(预处理)生成一个.i文件。在预处理阶段所做的有:
- 头文件的包含,将头文件的内容整个插入到代码中
- define定义符号的替换
- 注释的删除
预处理进行的都是文本的替换
2.编译阶段
一个.i文件经编译生成一个.s文件,把C语言代码翻译成汇编代码,其中所做的有:
- 语法分析
- 词法分析
- 语义分析
- 符号汇总
其中涉及了许多复杂的过程 ,具体请见《编译原理》,这里只对符号汇总做简单介绍。
符号汇总不会处理局部变量,它会梳理出全局的符号,并将其汇总。
3.汇编阶段
将.s文件转化成.o文件 (在windows环境下目标文件后缀为.obj Linux环境下的目标文件后缀为.o)
- 把汇编指令翻译成二进制的指令
- 形成符号表
符号表中记录了全局变量或者函数的符号名及其地址,对于找不到地址的函数,先赋给其一个无效的地址。
4.链接阶段
将所有生成的.o文件以及链接库链接起来,生成.exe的可执行程序,它所做的工作有:
- 合并段表
- 符号表合并和重定位
将不同文件中拥有相同的符号的地址进行处理,合并之后丢弃无效的地址,使一个符号对应一个唯一有效的地址 ,当找不到有效地址时,编译器会报错。因此,在连接的时候,编译器可以跨文件寻找函数。