编译和链接

发布时间:2024年01月19日

目录

?编辑

一:翻译环境:

1.预处理(预编译)

2.编译

3.汇编

4.链接

二,运行环境:


一:翻译环境:

翻译环境可以将源代码转化为可执行的机械指令,翻译环境包括编译和链接两大部分。

编译又可以分为:预处理(预编译),编译,汇编三大过程。

下面是翻译环境大致过程:

分析:

1.多个.c文件单独经过编译器编译生成后缀为.obj的目标文件,这个过程为编译

(在Windows环境下的目标文件后缀为.obj ,Linux环境下的为.o)

2.多个目标文件和链接库一起通过链接器链接最终生成可执行程序。

3.链接库:支持程序运行的的基本函数集合。

以gcc为列把编译详细拆解:如图所示

1.预处理(预编译)

如上图可以看到在编译过程中预处理后的文件带有 .i 后缀,做出的处理如下

将所有#define删除,并且展开所有宏定义。

处理所有条件编译指令:如#if ,#ifdef,#elif,#endif

处理#include预编译指令,将所有包含的头文件的内容插入到预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件。

删除所有注释

添加行号和文件名,方便后续编译器生成调试信息等。

保留所有#pragma的编译指令,编译器后续使用

注意:经预处理后的.i文件中不再包含宏定义,宏已经被展开。并且包含的头文件都被插入到.i文件

中。因此当我们无法知道宏定义或者头文件是否被包含正确的时候,可以查看预处理后的.i文件确认。

2.编译

编译就是将预处理后的文件进行:词法分析,语法分析,语义分析。之后生成相应的汇编代码文件。

词法分析:

语法分析:

语义分析

3.汇编

汇编是将由编译生成的汇编代码转化成机器可执行的指令,每一个汇编语句对应一条机器指令。

根据汇编指令和机器指令的一一对照表进行翻译,不做任何指令优化。

4.链接

链接是把一堆文件链接在一起生成可执行程序。

过程包括:地址和空间的分配,符号决议和重定位等问题。

链接解决了一个项目中多文件多模块相互调用的问题

test.c经过编译器处理生成test.obj

add.c经编译器处理生成add.obj

在test.c中引用了add.c中的add函数和a_c变量。

在test.c中每次使用add和a_c都需知道其地址,但由于每个文件是单独编译的,编译器在编译add和a_c时不知道其地址,先将调用的add和a_c地址搁置。等到最后链接时,由链接器引用到的add符号在其它模块中查找add的地址,然后将test.c中引用到add的指令修改,使其目标地址为真正add函数地址。对于a_c也是如此。这个地址修订过程叫重定位。

二,运行环境:

1.程序的运行需要载入内存,在有操作系统的的环境中,这个由操作系统完成。在独立的环境中程序的载入由手动安排。

2.程序一旦执行便开始寻找main函数

3.开始执行程序代码,程序会使用运行时的堆栈,储存函数的局部变量和返回地址。

4.终止程序,正常终止也可能意外终止。

文章来源:https://blog.csdn.net/2301_80026123/article/details/135698871
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。