
库是一组封装好的函数或方法,它们可以被多个程序复用,从而避免重复编写相同功能的代码。例如,标准的数学函数库、字符串操作库都属于常用的库。
根据链接方式的不同,库可以分为静态库和动态库。
动态库(Dynamic Library)是一种在程序运行时被加载的库。
.so(Shared Object)。.dll(Dynamic Link Library)。静态库(Static Library)是一种在编译时直接嵌入到程序中的库。
.a(Archive)。.lib。动态库的链接发生在程序运行时,操作系统会动态加载动态库并解析符号地址。
以 printf("Hello, world!\n") 为例:
printf 函数。printf 所在的动态库(如 libc.so)。libc.so 中 printf 的内存地址。printf 函数。gcc main.o -o main -L. -lhello -Wl,-rpath=.-L.:指定动态库路径。-lhello:链接动态库 libhello.so。-Wl,-rpath=.:指定运行时动态库的搜索路径。静态库的链接发生在编译时,链接器将静态库中的目标代码直接嵌入到可执行文件中。
以 printf("Hello, world!\n") 为例:
libc.a 中 printf 的代码嵌入到程序中。printf 的实现,运行时无需依赖外部库。gcc main.o -o main -L. -lhello -static-static:强制使用静态库进行链接。动态库与静态库的本质都是目标文件(.o 文件)的集合,区别在于它们的链接时机和使用方式,主要区别于程序运行时。
静态库是将多个目标文件打包成一个归档文件(如 .a 或 .lib)。
gcc -c hello.c -o hello.o
ar rcs libhello.a hello.oar rcs:创建静态库。gcc main.o -o main -L. -lhello当程序被加载进内存前,程序中的方法代码就已经通过静态库对应的代码进行替换嵌入了,所以当加载进内存后的程序大小就包括了所有嵌入的代码,会明显感受到静态链接的程序比动态链接的程序大很多。
动态库是将多个目标文件打包成一个共享库文件(如 .so 或 .dll)。
gcc -fPIC -c hello.c -o hello.o
gcc -shared -o libhello.so hello.o-fPIC:生成与地址无关的代码。-shared:生成动态库。gcc main.o -o main -L. -lhello -Wl,-rpath=.使用动态库动态链接的程序在加载进内存中时,动态库与程序一起加载到内存中。因为链接时是用动态库中关于程序中所需要的代码的地址进行链接,直接在库中进行运行后然后返回到程序,所以只需要加载进内存一份动态库,会节省很多内存。
特性 | 静态库 | 动态库 |
|---|---|---|
文件格式 | .a(Linux),.lib(Windows) | .so(Linux),.dll(Windows) |
链接时间 | 编译时 | 运行时 |
占用空间 | 程序体积较大,库内容被复制到程序中 | 程序体积小,库不被复制到程序中 |
更新方式 | 需重新编译程序 | 动态库可独立更新,无需重新编译 |
性能 | 高(不需要运行时加载库) | 稍低(运行时需加载和解析库) |
动态库和静态库各有优缺点,选择使用哪种库需要根据具体的项目需求来权衡。
区别:
无论是动态库还是静态库,它们的核心本质都是目标文件的集合,通过不同的链接方式为程序提供功能支持。理解它们的特点和使用方法,可以帮助开发者更高效地管理和复用代码资源。