C源文件到可执行文件的过程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhengqijun_/article/details/51881149

一、C源文件到可执行文件共经历了4个过程。在使用GCC编译程序时,编译过程可以被细分为四个阶段,包括预处理、编译、汇编、链接

1、预处理

在预处理阶段,编译器主要作加载头文件、宏替换、条件编译的作用。一般处理带“#”的语句。

我们可以通过gcc 的 -E 选项进行查看,如下所示:

[root@localhost 0001]#gcc -E main.c -o main.i

编译器将main.c预处理结果输出 main.i 文件。

2、编译

在编译过程中,编译器主要作语法检查和词法分析。我们可以通过使用 -S 选项来进行查看,该选项预处理之后的结果翻译成汇编代码。如下所示:

[root@localhost 0001]# gcc –S main.i

编译器将预处理输出文件main.i 文件编译成main.s 文件。

3、汇编

在汇编过程中,编译器把汇编代码转化为机器代码。我们可以通过-c 选项来进行查看,如下所示:

[root@localhost 0001]# gcc –c main.s

编译器将main.s 文件转化为main.o 文件。

4、链接

链接就是将目标文件、启动代码、库文件链接成可执行文件的过程,这个文件可被加载或拷贝到存储器执行。我们可以通过gcc main.o查看文件,如下所示:

[root@localhost 0001]# gcc –o main.o

编译器将输出文件main.o 链接成最终可执行文件a.out

 

链接可以执行与编译时(源代码被翻译成机器代码时),也可以执行与加载时(在程序被加载器加载到存储器并执行时),甚至执行与运行时,由应用程序来执行。在现代系统中,链接是由链接器自动执行的。链接器分为:静态链接器和动态链接器两种。

a.  静态链接器

静态链接器以一组可重定位目标文件和命令行参数作为输入,生成一个完全链接的可以加载和运行的可执行目标文件作为输出。

静态链接器主要完成两个任务:

  (1)符号解析:目标文件定义和引用符号。符号解析的目的在于将每个符号引用和一个符号定义联系起来。
  (2)重定位:编译器和汇编器生成从地址零开始的代码和数据节。链接器通过把每个符号定义和一个存储器位置联系起来,然后修改所有对这些符号的引用,使得他们执行这个存储位置,从而重定位这些节。

b.  动态链接器

动态链接方式下,函数的定义在动态链接库或共享对象的目标文件中。在编译的链接阶段,动态链接库只提供符号表和其他少量信息用于保证所有符号引用都有定义,保证编译顺利通过。动态链接器链接程序在运行过程中根据记录的共享对象的符号定义来动态加载共享库,然后完成重定位。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。  
目标文件有三种形式:
1> 可重定位的目标文件:
包含二进制代码和数据,其形式可以再编译时与其他可定位目标文件合并起来,创建一个可执行目标文件。
2> 可执行目标文件:
包含二进制代码和数据,其形式可以被直接拷贝到存储器并执行。
3> 共享目标文件:
一种特殊的可重定位目标文件,可以再加载或运行时,被动态地夹在到存储器并执行。编译器和汇编器生成可重定位目标文件(包括共享目标文件),链接器生成可执行目标文件。

 

gcc优化的方式:

1.  -O0:无优化(默认)。

2.  -O1:使用能减少目标文件大小以及执行时间并且不会使编译时间明显增加的优化.在编译大型程序的时候会显著增加编译时内存的使用。

3.  -O2: 包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化.编译器不执行循环展开以及函数内联.此选项将增加编译时间和目标文件的执行性能。(一般优化到-O2就可以了)

4.  -Os:专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项.并且执行专门减小目标文件大小的优化选项。

5.  -O3: 打开所有-O2的优化选项并且增加 -finline-functions, -funswitch-loops,-fpredictive-commoning, -fgcse-after-reload and -ftree-vectorize优化选项。

 

展开阅读全文

没有更多推荐了,返回首页