在c语言标准(ANSI C)中的任何⼀种实现中,存在两个不同的环境。
一个或多个源文件单独通过经过编译后生成一个或多个目标文件,多个目标文件经过链接库【链接库是指运⾏时库(它是⽀持程序运⾏的基本函数集合)或者第三⽅库】链接在一起生成可执行文件,可执行文件被机器直接指行的得出结果
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
编译分为预处理(预编译),编译,汇编三个过程
预处理阶段主要是执行预处理指令,例如头文件的包含,替换#define定义的代码,宏等
具体的工作:
预处理后的代码还是文本代码
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
编译过程就是将预处理后的⽂件进⾏词法分析、语法分析、语义分析及优化,⽣成相应的汇编代码⽂件。
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
扫描器将代码拆分为一个个的特殊记号(关键字,标识符,特殊字符,运算符等),方便编译器解析
词法分析时还会将拆分后的符号汇总,方便链接的进行
例
a[i] = i * (2 + j);
该行代码会被扫描器分成11个记号,分别为:
a , [ , i, ] , = , * , ( , 2 , + , j , )
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
语法分析器,将对扫描产⽣的记号进⾏语法分析,从⽽产⽣语法树
这些语法树是以表达式为节点的树
例
a[i] = i * (2 + j);
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
语义分析器来完成语义分析,即对表达式的语法层⾯分析。
编译器所能做的分析是语义的静态分析。
静态语义分析通常包括声明,类型的匹配,类型的转换等。
语义分析会报告错误的语法信息。
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
汇编器是将汇编代码转变成机器可执⾏的指令,每⼀个汇编语句⼏乎都对应⼀条机器指令。
汇编还会将编译的词法分析汇总的符号制成符号表【符号表就是多个符号+符号的地址所构成的表】,并将符号表传给链接库,方便链接
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
链接的时候需要把⼀堆⽂件链接在⼀起⽣成可执⾏程序。
链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。
链接解决的是⼀个项⽬中多⽂件、多模块之间互相调⽤的问题
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
C语言的链接过程中,地址和空间分配是一个重要的环节,它涉及到程序的内存布局,即程序在内存中如何分布及其各自的地址范围。
以下是链接过程中地址和空间分配的一些关键点:
文本段(Text Segment):
main
函数)。数据段(Data Segment):
堆(Heap):
malloc
、calloc
、realloc
等函数动态分配的内存都位于堆上。栈(Stack):
重定位表(Relocation Table):
动态内存分配(Dynamic Memory Allocation):
malloc
等函数),那么这些内存将在程序运行时由操作系统动态地分配和释放。一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
符号决议是指链接器在将多个编译后的目标文件合并成一个可执行文件时,
确定每个符号(如函数名、变量名等)所对应的具体地址的过程。
这个过程确保了程序在运行时能够正确地找到并调用所需的函数和访问变量。
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
在C语言程序链接过程中,重定位是一种重要的步骤,它涉及将不同的目标文件中的符号(函数或变量)的地址合并到一个单独的可执行文件中。
当多个目标文件需要访问同一符号时,编译器无法确定哪个文件中的符号地址应该被使用,因此需要进行重定位。
重定位是程序能够正确访问外部函数和变量的关键。
C语言链接过程中的重定位主要分为静态链接和动态链接两种方式。
在静态链接过程中,链接器会在编译后的目标文件中将所有的符号(函数名、变量名等)和它们的地址进行绑定,并将这些地址填写到可执行文件中。
这个过程称为重定位。当可执行程序被操作系统加载到内存中时,由于所有的符号已经在链接过程中被重定位,因此程序可以直接使用这些符号,而不需要再进行地址绑定
静态链接的优点是运行效率高,因为它在编译和链接阶段就已经完成了所有的重定位工作。但是静态链接也有一些缺点,比如占用物理内存较多,且无法实现动态更新。
与静态链接不同,动态链接在编译阶段不会将符号和地址进行绑定,而是仅仅在可执行文件或动态库中记录一些必要的信息。
这些信息包括符号名称、符号类型以及符号在动态链接器中的地址。当程序运行时,操作系统会首先加载可执行文件和动态链接器到内存中,然后通过动态链接器来完成符号的绑定和重定位工作。
动态链接的优点是可以节省物理内存,因为它不需要将所有的库函数都包含在可执行文件中。
此外,动态链接还可以实现动态更新,例如在程序运行过程中可以动态地加载或卸载库函数。
但是动态链接也有一个缺点,就是程序的运行效率相对较低,因为它需要在运行时进行符号绑定和重定位。
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
以上就是全部内容了,如果对你有帮助的话可以点个赞,支持一下