库(Library)本质上是一组预先编译好的函数、类或变量的集合,它们可以被你的程序复用,而无需你重新编写这些代码。
静态库(Static Library)
- 扩展名:在 Linux/Unix 中是
.a
(Archive),在 Windows 中是.lib
。 - 优点:部署简单,程序独立,运行速度快
- 缺点:体积大,多个程序共用时浪费空间,库更新需要重新编译整个程序
创建与使用(Linux示例)
mymath.h
(头文件,声明函数)
#ifndef MYMATH_H
#define MYMATH_H
int add(int a, int b);
int subtract(int a, int b);
#endif
mymath.c
(源文件,实现函数)
#include "mymath.h"
int add(int a, int b)
{
return a + b;
}
int subtract(int a, int b)
{
return a - b;
}
main.c
#include <stdio.h>
#include "mymath.h" // 包含我们的头文件
int main()
{
int a = 10, b = 5;
printf("%d + %d = %d\n", a, b, add(a, b));
printf("%d - %d = %d\n", a, b, subtract(a, b));
return 0;
}
命令执行
#1.编译为目标文件 (.o) ,-c 选项表示只编译不链接。
gcc -c mymath.c -o mymath.o
#2.创建静态库 (.a),使用 ar (archive) 命令将目标文件打包成库。
ar rcs libmymath.a mymath.o
#r:替换库中已有的文件或插入新文件。c:创建库(如果不存在)。s:创建索引,加快链接速度。
#3.使用静态库编译程序
gcc main.c -o main -L. -lmymath
#-L.:告诉编译器除了标准路径外,还在当前目录(.) 中寻找库文件。
#-lmymath:告诉编译器链接名为 mymath 的库。注意,编译器会自动添加 lib 前缀和 .a 后缀,所以我们只用写 -lmymath。
#4运行
./main
运行结果
10 + 5 = 15
10 - 5 = 5
此时,你可以删除 libmymath.a
,./main
依然可以运行,因为库代码已经复制到 main
可执行文件里了。
动态库(Shared Library / Dynamic Link Library)
-
扩展名:在 Linux/Unix 中是
.so
(Shared Object),在 Windows 中是.dll
。
- 优点:节省磁盘和内存空间(多个程序可共享),库更新无需重新编译主程序(接口兼容的前提下)
- 缺点:部署稍复杂,需要确保运行环境有正确的库版本,略微增加运行时的开销
创建与使用(Linux示例)
使用相同的 mymath.h
, mymath.c
, main.c
文件。
#1.编译为目标文件 (.o)
#编译时需要添加 -fPIC 选项,是动态库所必需的。
gcc -c -fPIC mymath.c -o mymath.o
#2创建动态库 (.so)
#-shared:告诉编译器生成一个动态库。
gcc -shared -o libmymath.so mymath.o
#3使用动态库编译程序
gcc main.c -o main_shared -L. -lmymath
#4运行
./main_shared
# 可能输出:./main_shared: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory
#原因:系统找不到 libmymath.so 文件。系统只在标准库路径(如 /lib, /usr/lib)和 LD_LIBRARY_PATH 环境变量指定的路径中查找动态库。
解决方法(选其一即可):
#临时方法(当前终端有效):
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./main_shared
#永久方法(拷贝到系统路径):
sudo cp libmymath.so /usr/lib
./main_shared
# 重新打开终端可以正常运行了
总结
-
使用静态库:当你希望程序独立分发,不想担心用户环境缺少依赖库时(例如,一些闭源商业软件)。或者对程序的启动速度有极致要求。
-
使用动态库:这是更常见的选择。尤其是系统级的库(如
glibc
)。当你的代码模块需要频繁更新时,动态库的优势非常明显。几乎所有 Linux 发行版都极力推荐使用动态库来节省空间。