C编译流程

C编译流程_第1张图片

1.预处理

hello.c 经过预处理得到 hello.i
gcc -E hello.c -o hello.i
-E的含义:说明这是一个预处理操作 生成预处理文件(.i)
预处理阶段做了什么事:

1.1 头文件展开

我们发现 原先只有几行的hello.c变成了上千行的hello.i
实际上 预处理完成的是 将头文件展开
所有#include的内容全部插入源代码
并且不会检查语法错误
因此 但凡被#include的文件
其所有文本内容都会被无脑插入源代码

1.2 宏定义替换

若#define x y 则将所有的x 以文本的层次 替换成y
什么叫做以文本的层次:
就是说这是无脑替换 不会检查语法错误 所以有时要注意运算顺序 加括号
专业术语就是:将宏名替换为宏值

1.3 删除注释

注释是给人看的 计算机不看这些 将注释替换位空行

1.4 展开条件编译

根据实际的define情况
在代码中智能添加 //dosomething

2.编译

hello.i 经过编译得到 hello.s
gcc -S hello.s -o hello.s
-S的含义:说明这是编译操作 生成汇编文件(.s)
(也可以从源文件一步到达.s)
注意是大写S 生成的文件格式是小写s

生成汇编指令
向下翻译 生成了约几十行的文本内容
这是 最接近底层 最接近机器语言的汇编语言(汇编指令)
编译过程会检查语法错误 如果语法不正确 则无法生成汇编语言
相比之下 预处理过程不会检查语法错误
因此 编译过程是整个4步骤过程中最耗时的 因为语法错误要逐行检查

3.优化

优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化一部分是对中间代码的优化。这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的。上图中,我们将优化阶段放在编译程序的后面,这是一种比较笼统的表示。
对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。
后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题。
经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器指令,方可能被机器执行。

4.汇编

hello.s 经过汇编得到 hello.o
gcc -c hello.s -o hello.o
-c的含义:说明这是执行汇编操作 生成目标文件(.o)
(也可以从源文件一步到达.o)

汇编指令被翻译成了二进制的机器指令
通常在记事本中以十六进制形成呈现

汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。

5.链接

gcc hello.o -o hello.exe
1.数据段合并
2.数据地址回填
3.库引入

由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。
根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
(1)静态链接 在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。(个人备注:静态链接将链接库的代码复制到可执行程序中,使得可执行程序体积变大)
(2)动态链接  在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。(个人备注:动态链接指的是需要链接的代码放到一个共享对象中,共享对象映射到进程虚地址空间,链接程序记录可执行程序将来需要用的代码信息,根据这些信息迅速定位相应的代码片段。)
对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。
C编译流程_第2张图片

你可能感兴趣的:(编译链接,c语言,开发语言)