下图的过程就是在linux上面的编译执行过程。
直接使用gcc编译,则会生成默认的可执行文件a.out,如果想要指定生成文件名,则使用-o选项进行指定,这里面指定生成的文件名为test.exe。
使用man gcc来查看,gcc不仅包括了-o选项,还包括了-E,-S,-c等选项。而执行这些选项,则能够更加直观的了解从源码到可执行文件的不同阶段。 gcc test.c 主要包括1、预处理;2、编译;3、汇编;4、链接这四个阶段。
预处理:
gcc -E test.c -o test.E生成的test.E是经过预处理后的文件(这里面取名叫做test.E是为了方便识别该文件是预处理阶段的产物),对比test.E以及test.c的内容可以发现,test.E中增加了很多的内容,包括printf以及exit等函数的声明原型,这是对#include<stdio.h>以及#include<stdlib.h>的展开(printf在stdio.h中,exit在stdlib.h中)同时在该文件的最后也看到PRINTSTR宏展开以及注释的删除。因此在预处理阶段,预处理器主要的工作是对头文件,宏进行展开,对注释进行删除等工作。
编译:
gcc -S test.c -o test.S生成的test.S是编译生成的汇编指令文件,可以看到生成了一堆汇编指令代码。
汇编:
gcc -c test.S -o test 生成test是机器指令文件。这时候执行./test会提示该文件是不可执行的二进制文件,因为还需要最后一步的链接工作,也就是文件不齐全。
链接:
无论是动态的链接还是静态的链接就是把程序所需要的文件统一起来,生成最终的可执行文件。虽然我们只有test.c这一个文件,但是让程序跑起来,还是需要诸如程序的启动,结束等目标文件,如图中的crt1.o, crti.o等文件,因此链接命令需要将这些目标文件进行统一。这也是为什么上面的test文件运行不起来的原因,因为找不到程序的入口地址。 以上的四个步骤gcc test.c -o test.exe就可以直接搞定,但是通过上述的分解,我对整个编译的过程有了更多的了解。其实gcc是完成了对预处理器,编译器,汇编器以及连接器的封装工作。 村中少年 认证博客专家 网络安全 IDS/DPI 网络协议 网络安全工程师,计算机科学与技术本硕,多年从事IDS网络入侵检测,DPI深度报文检测等网络安全引擎方面经验,热爱技术,分享知识