静态库制作
编写库文件
test.c
#include<stdio.h>
int main(void){
printf("%d\n",add(3,5));
return 0;
}
add.c
int add(int a,int b){
return a+b;
}
生成.o(目标文件)
用nm查看.o文件
T代表add这个函数的链接性是外部链接,即全局可见,可被其它函数访问
创建库文件
命令的解释如下:
ar:这是归档工具的命令。
rc:选项rc用于创建一个新的归档文件,并添加文件到其中。r代表插入(replace),c代表创建(create)。
1ibtest.a:这是要创建的静态库文件的名称,.a扩展名表示这是一个静态库文件。
add.c是要被添加到静态库中的编译后的源代码文件。
链接库
-L.:这是gcc的一个选项,表示链接器应该在当前目录(.)下搜索库文件。-L选项后面通常跟的是库文件的路径,这里指定为当前目录。
-ltest:这是告诉gcc链接器链接名为libtest的库(库文件的命名约定通常是lib开头,.a或.so结尾,例如libtest.a或libtest.so)。-l选项后面跟的是库的名称,不包括前缀lib和后缀。.a一般是静态库,.so一般是动态库。
如果libtest.a或libtest.so存在于当前目录下,gcc将会链接这个库到最终的可执行文件中。如果库文件不存在,编译过程可能会报错,提示找不到库文件。
链接库之后出现warning,但是仍然可以生成可执行文件,warning的大概意思就是说add()这个函数在main函数中没有显性声明,而之所以不报错的原因在于gcc编译器会自动帮你补充声明
但是我们仍然可以在test.c中声明一下,看看声明以后的链接库的结果
不会warning
执行a.out
输出8
比较链接前后add函数的地址
可以看到add函数被链接之后被分配了内存,而其它的变量与函数也是一样的,在链接之后分配内存,然后,执行文件便可以通过地址去调用和访问它们
查看libtest.a
可以看到库里包含add.o文件,对于其中的函数add()还没有分配内存
添加新文件到库
编写sub库函数
int sub(int a,int b){
return a-b;
}
生成sub目标文件
将sub.o添加到原有的库libtest.a
nm查看libtest.a
可以看出这个库中的文件多了一个,但是他们的函数都没有被分配内存
再次链接
再次执行
输出8和-2符合与其输出
总结
执行test.c文件,链接文件去链接需要的变量和函数,当链接到add()和sub()时就去libtest.a静态库中寻找对应的符号(包含变量和函数)),通过这个符号便可以确定代码段的地址,再将地址填入调入指令。
静态库的的缺点
在a.out可执行文件中包含了所有test.c需要的文件,所以a.out将会占用较大的磁盘空间。
而当有多个进程同时调用同一个函数时,那每一个进程的可执行文件都将包含一份被调函数的副本,这又会造成系统内存负担过重。