gcc hello.c 执行时其实分成了四个步骤:预处理,编译,汇编,链接。
1. 预处理(预编译)
现在有程序hello.c,预处理生成.i文件。linux中预处理.c文件生成.i文件的指令如下:(两条中的任何一条都可以)
$gcc -E hello.c -o hello.i
$cpp hello.c > hello.i
预处理主要处理以#开头的预编译指令。
- 处理#include ,#define等指令。
- 删除所有注释//和/* */
- 添加行号和文件标识名
- 保留所有#pragma编译指令
预编译之后的.i文件不包含宏定义,因为宏定义都已经被展开了。包含的文件也已经被插入到.i文件中。因此当我们无法判断宏定义是否正确或者头文件包含是否正确的时候可以查看.i文件来确定问题。
2.编译
词法分析,语法分析,语义分析以及优化之后生成相应的汇编文件。
$gcc -S hello.i -c hello.s
3.汇编
将汇编代码转换成机器可执行的命令。一下三条语句都可以达到目的:
$as hello.s -o hello.o//as为汇编器
$gcc -c hello.s -o hello.o//从编译后的文件到目标文件
$gcc -c hello.c -o hello.o//从源文件直接编程目标文件
4.链接
一个程序被分隔成为多个模块之后,这些模块之间如何形成一个单一的程序是需要解决的问题。模块之间的组合问题其实是模块之间的通信问题,类似于拼版图,因为要处理不同模块之间的公用变量或者代码段对问题。这个过程就需要通过链接来解决。
人们将每个源代码模块独立地进行编译,之后按照需要将它们组装起来,这个过程就是链接。链接过程主要包括了地址和空间的分配、符号决议和重定位等步骤。
每个模块的源代码文件经过编译器编译形成目标文件,目标文件和库一起链接形成可执行文件。