在c语言中将源程序转换为可执行代码主要分为编译和链接两步,工程中的每个.c源文件经过编译器的编译分别变成.o目标文件,每个.o目标文件通过链接器捆绑在一起形成可执行程序,链接器同时也会引入程序中引用的标准c库函数。
编译
编译又分为预处理(预编译),编译,汇编三部分。
①预处理阶段:预处理阶段主要进行一些文本操作,包括#include头文件的包含,#define宏定义的替换以及注释的删除,预处理会把各个.c文件变成.i文件。
②编译:编译阶段主要是把c语言代码转换成汇编代码,包括语法分析,词法分析,符号汇总和语义分析,只需要了解符号汇总部分,主要是将.c文件中的全局变量和函数名进行汇总,局部变量是程序运行时进入到这个局部范围才会创建,这里不会汇总,编译会将各个.i文件变为.s文件。
③汇编:汇编阶段主要把.s汇编代码转换成.o目标文件(二进制机器指令),还会利用编译阶段汇总的符号形成符号表,赋予符号地址,便于后续管理。
链接
链接过程是将各个.o目标文件和链接库捆绑起来生成.exe可执行程序,其中对符号表进行了合并和重定位,下面举一个例子来进行说明:
因为main.c中的Add是函数声明而不是函数实现,可以理解为虚假的符号,不能指向函数的真实地址,所以在符号表合并时,虽然有两个Add,但是真实的是Add.c中的地址,我们在写代码时可能会出现这种错误,函数调用却没有定义,就相当于没有在Add.c中定义函数,却在main.c中调用了,就会在链接时出错。