前言
对于给定的hello.c程序:
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
执行命令
gcc hello.c
./a.out
之后,gcc在背后都做了什么处理?本文介绍了C语言程序由代码到可执行文件的转化过程,大致分为:预处理、编译、汇编、链接。
一、预处理
可以使用如下命令:
gcc -E hello.c -o hello.i
得到预处理后的.i文件。预处理过程主要处理文件中的以"#“为开头的预编译指令,如#define、#include等。主要处理规则如下:
1、将所有的”#define"删除,并展开所有的宏定义;
2、处理所有的条件预编译命令,如#if、#ifdef、#elif、#else、#endif;
3、处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。这个过程是递归进行的,被包含的文件可能也包含了其他文件;
4、删除所有注释;
5、添加行号和文件名标识;
6、保留所有的#pragme编译器指令,因为编译器需要使用它们。
经过处理后的.i文件不包含任何宏定义,因为所有宏定义均已被展开。
二、编译
可以使用如下命令:
gcc -S hello.i -o hello.o
或者直接将前两步合为一步:
gcc -S hello.c -o hello.o
编译过程就是将预处理完的文件进行一系列的词法分析、语法分析、语义分析以及优化后产生相应的汇编代码文件。
三、汇编
可以使用如下命令:
gcc -c hello.o -o hello.s
或者直接将前三步合为一步:
gcc -c hello.c -o hello.o
汇编器是将汇编代码转为机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令,汇编器根据汇编指令和机器指令的对照表一一翻译即可。
四、链接
链接是将各种代码和数据片段收集并组合成一个单一文件的过程,这个文件被加载到内存并执行。
参考文章
1、程序员的自我修养
2、深入理解计算机系统