小豆丁:老张!老张!
老张:干嘛?
小豆丁:咋啦?愁眉苦脸的,是不是又被媳妇给揍了?
老张:开玩笑,我在家那就是相当于老虎的存在,谁敢揍我!
媳妇:老张,你说啥?我没听清,你再说一遍?
老张:我是老虎,你是武松......
小豆丁:哈哈哈...哈哈哈...老张!你又怂了...
老张:要是没事的话就赶紧给我圆润的离开!!!
小豆丁:有事有事!嘿嘿,我想问问,啥事可执行程序啊?
老张:就是可以执行的程序。
小豆丁:额...具体说说呗...
老张:哼,不想说!
小豆丁:我错了,老张,不该笑话你,你就跟我说说吧!
老张:看在你态度还算诚恳的态度上,就跟你说说吧!可执行程序,实际上就是计算机可以执行的指令的集合,我们在电脑上写好的程序代码,经过编译器的编译,最终形成的就是可执行程序,这样计算机就可以按照代码中想要表达的功能进行工作了。
小豆丁:那编译器是怎么把代码编程可执行程序的啊?
老张:这个过程就有点复杂了。我们以Linux操作系统gcc编译器为例,来看下对C程序的编译处理过程。
小豆丁:嗯嗯,快讲吧,我已经准备好记录了!
老张:计算机只认识二进制0和1这种文件,而我们写的C程序显然不是二进制文件,这就需要编译器对我们写好的程序进行编译,使之变成计算机可以识别的二进制文件,也就是你刚刚所问的可执行程序。从C程序文件到可执行程序,可以分为四个过程。
小豆丁:哪四个过程啊?
老张:第一个就是预处理过程,可以通过gcc编译器配合用-E选项进行处理,比如下图,有一个写好的C语言程序,
通过gcc -E hello.c -o hello.i指令,我们可以完成hello.c文件的预处理操作,将预处理操作之后得到的结果保存到hello.i文件中。
小豆丁:那预处理阶段编译器都做什么工作了。
老张:这个问题问得好,我们可以打开hello.i文件,看看预处理之后的得到的内容,如下图。
从图中我们可以看到,代码有原本的五六行扩充到了八百多行。这是因为在原本程序中,我们通过预处理指令#include包含了头文件stdio.h,编译器在预处理过程中会将包含的头文件替换进我们的程序中,所以看到预处理后文件的代码量增加很多。
小豆丁:那预处理阶段只是进行头文件的替换吗?
老张:当然不是了,在预处理阶段,除了头文件的替换之外,还会进行宏替换和条件编译的处理。
小豆丁:哦哦,我记住了,那第二个阶段呢?
老张:第二个阶段叫做汇编阶段,我们可以通过gcc -S hello.i -o hello.s指令完成操作,将hello.i文件进行汇编处理,将处理后得到的内容存放到hello.s文件中。如下图
小豆丁:这个阶段都做了什么工作啊?
老张:我们可以打开hello.s文件看下,发现文件内容已经不是C语言的代码了,在这个阶段,编译器会把我们的代码转换成汇编指令,如下图
小豆丁:是不是从C语言的代码转换成汇编指令,计算机就更容易理解和执行了?
老张:你说得对,值得表扬!
小豆丁:哈哈,本豆丁也是很聪明的,励志要称为一名优秀的程序员!
小豆丁:那第三个阶段是什么啊?
老张:第三个阶段是编译阶段,在这个阶段编译器会将汇编文件转换成二进制文件,我们把转换后的二进制文件称为目标文件,可以用gcc -c hello.s -o hello.o指令完成操作,具体如图。
小豆丁:老张,这个hello.o文件我打开后怎么看不懂啊,都是乱码啊?
老张:看不懂是正常的,因为这是个二进制文件,已经不是我们所能理解的代码范畴内了。
小豆丁:既然这是一个二进制文件,是不是计算机就能理解了?是不是我们就可以执行它了?
老张:还不能,虽然hello.o是一个二进制文件,但是还不能执行,我们还需要最后一步操作,叫做链接,将程序执行过程中需要用到的一些库和运行时文件链接到hello.o上,形成最终的a.out可执行程序,才能运行。
小豆丁:哦,还要链接库和相关文件啊,那最后一步怎么操作啊?
老张:最后一步比较简单,用gcc hello.o指令就可以,最后会生成可执行程序a.out,这个时候就可以运行了,如下图。
小豆丁:哦,我懂了,我们写好的C语言程序,要经过编译器编译才能成为可以运行的程序,而这个编译的过程分为四步,分别是预处理、汇编、编译和链接,每一步都有自己的功能和作用。
老张:不错不错,孺子可教也。
小豆丁:谢谢老张,我走了,赶紧回去敲个代码试试去!哈哈!
小豆丁:还有啊,没事不用总惹你媳妇生气了,看把你揍的!
老张:......
老张:喜欢老张的话,就关注我吧,每天分享一个IT小知识!
领取专属 10元无门槛券
私享最新 技术干货