C程序编译过程

Linux程序员可以根据自己的需要让gcc在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。
编译过程主要分为以下几步:
1.预处理(Preprocession)
2.编译(Compliation)
3.汇编(Assembly)
4.链接(Linking)

以hello.c程序为例:在这里插入图片描述

一.预处理(Preprocession)

预处理是读取c源程序,对其中的伪指令(以#开头的指令,也就是宏)和特殊符号进行替代的处理,经过预处理,生成一个没有条件编译,没有宏定义,没有特殊符号的输出文件,这个文件的含义和没有经过预处理的源文件是相同的,仍然是c文件,但内容有所不同,伪指令主要包括以下三个方面:
1.宏定义指令
2.条件编译指令
3.头文件包含指令

预处理具体主要包括以下过程:
1.将所有的#define删除,并且展开所有的宏定义。
2.处理所有的条件编译指令,如#ifdef #elif #else #endif。
3.处理所有头文件包含指令#include,将包含的文件插入预编译指令的位置。
4.删除所有的注释。
5.添加行号和文件标识,以便编译时产生调试用的行号和编译错误警告行号。
6.保留所有的#pragma编译器指令,因为编译器需要它们。

gcc编译时,通常指定“-E”选项来表明只进行预处理,例如hello.c文件,指定-E选项后则会生成hello.i的只进行了预处理的文件。

二.编译(Compilation)

编译程序所要做的工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
使用以下命令进行编译则生成汇编文件。

ubuntu-master:~$ gcc -S hello.i > hello.s

ubuntu-master:~$ /opt/xtools/arm920t/bin/arm-linux-gcc -S hello.i > hello.s

我们使用pc的编译器编译c源程序,就会生成x86的汇编,而使用arm的编译器,则会生成ARM的汇编。同样一份c源程序,使用不同的编译器就会生成不同汇编文件,最终在不同的机器上运行,这就是c程序的可移植性。所谓的交叉编译就是在PC上使用ARM的编译器来编译程序,生成可以在ARM平台上运行的程序。

三.汇编(Assembly)

汇编就是把汇编语言代码翻译成目标机器指令的过程。每一个c源程序,都将经过这一步而得到相应的目标文件。目标文件中存放的就是与源程序等效的目标的机器语言代码。目标文件由段组成,通常一个目标文件中至少有两个段。
1.代码段:存放程序的指令,一般可读和可执行,但不可写。
2.数据段:存放程序中用到的各种常量,全局变量,静态的数据,一般可读,可写,可执行。
gcc编译选项中“-c”选项指定只编译,汇编,不链接,生成以“.o"为后缀名的目标文件。

四.链接(Linking)

汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,
都需要经链接程序的处理方能得以解决。 链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体,也就是可执行程序。 根据开发人员指定的库函数的链接方式的不同,链接处理可分为两种:
1.静态链接
2.动态链接

对于可执行文件中的函数调用,可分别采用静态链接或动态链接方式,使用动态链接可以使最终的可执行文件比较短小,并当共享对象被多个进程使用时能节约一些内存。但并不是动态链接一定优于静态链接,某些情况下使用动态链接会带来一些性能上的损害。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值