1. 静态链接库与动态链接库
程序编译时发生的动作称为静态行为,程序运行时发生的动作称为动态行为。故链接共分为两种,静态链接和动态链接。目前来看,链接使用的原因在于,主程序文件执行时需要引入头文件,执行外部函数。而引入头文件时,在编译阶段确定外部函数的地址还是在运行阶段确定外部函数的地址,由此产生了静态链接和动态链接两种方案。
静态链接是在编译阶段确定外部符号地址,并将依赖的符号其对应的目标文件与主程序文件一同编译,形成最后的可执行程序。
动态链接是在程序运行期间,根据程序需要,在动态链接库加载时才确定外部符号的地址。动态链接库不需要打包到可执行程序中,只需要存在于特定的路径中。
动态链接库是共享的,任意程序都可加载。动态链接库在 Linux 系统下后缀为 .so,在 Windows 系统下后缀为 .dll,在 Mac 系统上为 .dylib。而静态链接库只存在于某个特定的程序文件中,不能共享。静态链接库在 Windows 系统下后缀为 .a。
2. 编译静态链接库
例如,对主程序文件为 02.static_library.c 文件进行静态链接库的编译。主程序 02.static_library.c 文件引入 factorial.h 和 fibonacci.h 头文件,从而执行 Factorial() 和 Fibonacci() 函数。其编译静态链接库的具体过程如下:
1)准备工作,创建 mathutils 文件夹及相应的 .h 头文件和 .c 文件
2)将主程序文件 02.static_library.c 中引用的外部函数的所在 .c 文件编译为目标文件。
3)使用 ar(类似于打包的 zip 命令)将目标文件进行打包,生成 .a 文件,即生成静态链接库。ar 命令使用时添加了三个参数 r c s,可使用 ar -h 查看各参数功能。r 表示将新文件进行打包,c 表示新建包时不发出警告,s 表示创建包的索引。(r:replace existing or insert new file(s) into the archive. c:do not warn if the library had to be created s:create an archive index)
此外,可使用 ar t 进行打包文件的查看(t:display contents of the archive)
4)此时,未添加静态链接库,而直接编译主程序文件 02.static_library,其运行结果如下图所示。错误原因为主程序文件找不到头文件中引用的 Factorial() 和 Fibonacci() 函数。
解决方法为添加静态链接库进行编译,其结果如下。实质上,不一定非要 .a 文件,直接添加待引用函数的 .o 文件也可达到同样效果。但缺点在于,若添加的 .o 文件过多,.a 文件较 .o 文件更为方便。