提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
最近系统了解了一下C语言的编译过程,以上是我的总结,如有错误,请大家及时纠正,建议也可评论,感谢观看。
C语言编译生成可执行文件过程
1、 预处理
linux下可以用下面操作得到.i文件,为经过预处理之后的文件:
gcc hello.c -o hello.i -E
//将得到一个.i的文本文件
预处理需要完成的工作有以下内容:
* 头文件被包含进来:#include
* 宏定义替换:#define
* 取消宏定义:#undef
* 条件编译:#if #ifdef ……
* 修改行号以及文件名:#line 998 “Hello.c”
* 清除注释
预处理处理的工作大部分都是带#的,工作都是由”预编译器“来处理。
2、编译
linux下可以用下面操作得到.s汇编文件,为经过编译之后的文件:
gcc hello.i -o hello.s -S //.s为汇编文件
打开文件可以发现里面是符合x86的汇编文件,汇编文件取决于采用的编译器,如果是GCC,那么生成的则是x86格式的汇编,如果是用的ARM平台的交叉编译器,则生成符合ARM格式的汇编文件。
3、汇编
linux下想得到一个后缀为.o的文件可用以下语句:
gcc hello.s -o hello.o -c //这里可以生成一个代链接的可执行文件.o
生成一个扩展名为.o 的文件,这个文件是一个 ELF 格式的可重定位(relocatable)文件,所谓的可重定位,指的是该文件虽然已经包含可以让处理器直接运行的指令流,但是程序中的所有的全局符号尚未定位,所谓的全局符号,就是指函数和全局变量,函数和全局变量默认情况下是可以被外部文件引用的,由于定义和调用可以出现在不同的文件当中,因此他们在编译的过程中需要确定其入口地址,比如 a.c 文件里面定义了一个函数 func( ),b.c 文件里面调用了该函数,那么在完成第三阶段汇编之后,b.o 文件里面的函数 func( )的地址将是 0,显然这是不能运行的,必须要找到 a.c 文件里面函数 func( )的确切的入口地址,然后将 b.c 中的“全局符号”func重新定位为这个地址,程序才能正确运行。因此,接下来需要进行第四个阶段:链接。
4、链接
linux下想得到一个后缀为.o的文件可用以下语句:
gcc hello.o -o hello -lc -lgcc
gcc .....
hello.o ....
-o ......
hello .....
-lc --> -l 链接 c 标准C库
-lgcc --> -l 链接 gcc 链接GCC 的库
有两个很重要的工作没完成,首先是重定位,其次是合并相同权限的段
一个可执行镜像文件可以由多个可重定位文件链接而成,比如 a.o,b.o,c.o 这三个可重定位文件
链接生成一个叫做 x 的可执行文件,这些文件不管是可重定位的,还是可执行的,它们都是 ELF 格式的,ELF 格式是是符合一定规范的文件格式,里面包含很多段(section),比如我们上面所述的 hello.c
编译生成的 hello.o 有如下的格式

图形化如下:


1530

被折叠的 条评论
为什么被折叠?



