前言
如果你使用集成环境开发。那么你点击编译按钮就可生成可执行文件。但是C程序从源代码到二进制行程序都经历了那些过程?你知道吗?这些过程集成开发环境在点击编译按钮后都做完了,如果编译没有出错,即可生成可执行文件。本文将以Linux下C语言的编译过程为例。对编译过程进行讨论。
编译一个C程序代码
下面以Linux环境下的test.c为例,test.c里的代码为:
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("hello 程序猿编码n");
return 0;
}
编译输出:
这个过程如此熟悉,以至于觉得编译是一件很简单的事。事实真的如此吗?我们来细看一下C语言的编译过程到底是怎样的。
GCC编译过程:
图片来源于:GCC和Make编译,链接和构建C/C ++应用程序
上述gcc命令其实依次执行了四步操作:
1.预处理(Preprocessing)
2.编译(Compilation),
3.汇编(Assemble),
4.链接(Linking)。
预处理
以“#”号开头的预处理指令如包含#include,宏定义制定#define等。在源程序中这些指令都放在函数之外,而且一般放在源文件的前面。
使用预处理器把源文件test.c经过预处理生成test.i文件。
预处理的命令为:
gcc -E test.c -o test.i
上述命令中-E是让编译器在预处理之后就退出,不进行后续编译过程;-o是指定输出文件名。在本例中,预处理结果就是将stdio.h 文件中的内容插入到test.c中了。
预处理生成的是test.i的文本文件,这个文本文件是可以直接通过cat命令进行文本文件查看的。
对比预处理、文本文件、可执行文件的大小
经过预处理之后代码体积会大很多,相当于可执行文件一倍大小。预处理之后的程序还是文本,可以用文本编辑器打开。
编译
这里的编译不是指程序从源文件到二进制程序的全部过程,而是指将经过预处理文件(test.i)之后的程序转换成特定汇编(test.s)代码的过程。
编译的命令为:
gcc -S test.i -o test.s
上述命令中-S让编译器在编译之后停止,不进行后续过程;-o是指定输出文件名。编译过程完成后,将生成程序的汇编代码test.s,这也是文本文件。
查看汇编代码和代码大小:
编译成汇编文件大小已经非常小了,没有像预处理的时候文件大小这么臃肿。
cat test.s
里面汇编是什么意思,就不要问我了。哈哈~
汇编
汇编过程将上一步的汇编代码转换成机器码,这一步产生的文件叫做目标文件,是二进制格式。
编译的命令为:
gcc -c test.s -o test.o
部分内容截图如下:
链接
链接过程使用链接器将该目标文件与其他目标文件、库文件、启动文件等链接起来生成可执行文件。附加的目标文件包括静态连接库和动态连接库。
链接过程的命令为:
gcc test.o -o test
总结
生成可执行程序过程为成四个步骤:
1、由.c文件到.i文件,这个过程叫预处理。
2、由.i文件到.s文件,这个过程叫编译。
3、由.s文件到.o文件,这个过程叫汇编。
4、由.o文件到可执行文件,这个过程叫链接。
欢迎关注微信公众号“程序猿编码” ,这里Linux c/c++ 、Python、Go语言、数据结构与算法、网络编程相关知识,常用的程序员工具。每日00:10之前更新新闻简报,一份简报,纵览天下事!