在步入工作岗位之后,重新对编程是个什么过程进行了了解
简单的来说,我们平常所写的代码经过编译和链接之后生成可执行文件,下面就编译和链接两个过程分别讨论
编译阶段
编译阶段需要的素材就是你的源文件,把源文件经过一系列神奇的编译操作变成目标文件就是我们的目的,也就是linux系统下使用gcc -c得到的目标文件
预处理简单来说就是宏的展开和头文件的包含,把#include的东西全都复制进去,把文件变大,但是语言本质并没有改变,也就是说你的C还是原来的C
编程语言到汇编语言就是编译器做的工作了,一个好的编译器在这里会下很大的功夫。
可以这么理解,汇编语言和机器语言基本是等价的,区别只不过是汇编语言还是给人看的,机器语言已经不是给人看的了是给机器看的(当然你要是精通机器语言也是吼的),为什么这么说?每一条汇编语言都有机器语言去对应,每一个汇编命令都是一串二进制码
编译的结果是生成目标文件,每一个编译单元生成对应的一个目标文件,这里还是可以参考linux系统下的gcc -c,使用这条命令的时候会把每个.c文件的文件名拿来直接生成对应的.o文件(就是helloworld.c->helloworld.o)
链接阶段
上图是各个文件相互转化的图。目标文件可以直接生成可执行文件,也可以做成动态库或者静态库,静态库可以链接另一个静态库变成一个更大的库。诸如此类的转化
提到链接就有很多熟悉的名词和概念要提
静态库
静态库在程序编译的时候会被链接到目标代码当中,所以在程序运行的时候就不再需要静态库啦,相当于可执行程序把静态库包含了。
动态库
与静态库相对的动态库,在程序编译的时候并不会被链接到目标代码当中,而是在程序运行的时候才被载入,因此在程序运行的时候还需要动态库的存在,这就是在运行一些软件的时候你会看到一个警告框,提醒你缺少某个.dll文件的原因
静态链接
静态链接是指在链接的过程中直接将需要执行的代码(函数)拷贝到调用的地方,在程序运行的时候不在需要依赖链接的库,也不用带着库一起发布,程序就可以独立运行,但是程序的体积可能会大一些,因为会把一些代码塞进可执行程序里面
动态链接
与静态链接相对的,动态链接不会在链接的过程中把代码拷贝到调用的地方,动态链接会把调用的地方记录一些符号和参数(例如生成一个函数对应的符号),在程序运行到这个调用的地方的时候,可执行程序会把这些符号和参数传递给操作系统,操作系统会根据需要把对应的动态库加载到内存,然后可执行程序就可以去这段内存中寻找动态库中的代码,同时因为加载到共享的内存中可以供多个程序共同使用,这就是所谓的运行时链接。相比静态链接来说,由于不向可执行程序中拷贝代码,使得程序的体积在一定意义上减小了。因为动态链接将库加载到内存,省去了在各个程序中的拷贝,减少了磁盘的占用,可以让多个程序共享使用。但是缺点是加载需要一定的时间,可能会影响一定的性能
总结
一般来讲,静态链接和静态库对应使用,动态链接和动态库对应使用。据说有方法可以有别的使用方法,这里就不讨论了,有兴趣的可以搜索下