编译4步骤:预处理,编译(涉及到语法检测,相比其它步骤,消耗时间和系统资源最多),汇编,链接
预处理:(gcc -E hello.c -o hello.i) 展开宏,头文件,替换条件编译;删除注释,空行,空白部分
编译:(gcc -S hello.i -o hello.s)进行词法分析、语法分析、语义分析,输出汇编代码文件
汇编:(gcc -c hello.s -o hello.o)将汇编指令翻译成机器指令
链接:(gcc hello.o -o hello)数据段合并(数据段的合并是将只读的代码区和存储区合并,还有将全局区的bss段,Data段合并,目的是节省空间。因为内存最小的开辟内存空间单位是页,一页=4k。),地址回填(一个程序可能编译出多个目标文件,在转化为.o文件时,.o文件中对函数的调用和对全局变量的使用,一律用一套“重定位回填地址”的策略来暂时取代直接写入实际地址。这套策略依靠重定位表、符号表和字符串表来实现。当把.o文件链接成可执行程序时,再根据这些表来算出准确的地址位置,回填到应填写实际地址的位置)
gcc其它参数介绍:
-I 指定头文件所在目录
-c 只做 预处理,编译,汇编 得到二进制文件
-g 编译时增加调试语句,主要支持gdb调试
-wall 显示所有警告信息
-D 向程序中“动态”注册宏定义
-l 指定动态库名 (如 libexample.so 只用 example)
-L 指定动态库路径
汇编后的文件(二进制格式)布局
图片摘自:编译系统透视原理
进程内存空间占用图示(其中代码区和只读数据区合并;全局区的bss段,Data段合并):
图片截自:https://www.bilibili.com/video/BV1Q7411e7Un?p=35