1.库是预编译的目标文件(object files)的集合,它们可以被链接进程序。静态库以后缀为”.a”的特殊的存档(archive file)存储。
2.标准系统库可在目录/usr/lib与/lib中找到。比如,在类Unix系统中C语言的数序库一般存储为文件/usr/lib/libm.a。该库中函数的原型声明在头文件/usr/include/math.h中。
3.C标准库本身存储为/usr/lib/libc.a,它包含ANS1/ISO标准指定的函数,比如printf。对每一个C程序来说,libc.a都默认被链接。
在 Linux 中静态库以 lib 作为前缀,以.a 作为后缀,中间是库的名字自己指定即可,即: libxxx.a
在 Windows 中静态库一般以 lib 作为前缀,以 lib 作为后缀,中间是库的名字需要自己指定,即: libxxx.li
生成静态库,需要先对源文件进行汇编操作 (使用参数 -c) 得到二进制格式的目标文件 (.o 格式), 然后在通过 ar 工具将目标文件打包就可以得到静态库文件了 (libxxx.a)。
生成静态链接库的具体步骤如下:
1.需要将源文件进行汇编,得到 .o 文件,需要使用参数 -c
# -c 参数位置没有要求 $ gcc 源文件(*.c) -c
2.将得到的 .o 进行打包,得到静态库
$ ar rcs 静态库的名字(libxxx.a) 原材料(*.o)
3.发布静态库
# 发布静态库 1. 提供头文件 **.h 2. 提供制作出来的静态库 libxxx.a三.静态库举例
1. 准备测试程序
加法计算源文件 add.c:
#include#include "head.h" int add(int a, int b) { return a+b; }
减法计算源文件 sub.c:
#include#include "head.h" int subtract(int a, int b) { return a-b; }
乘法计算源文件 mult.c:
#include#include "head.h" int multiply(int a, int b) { return a*b; }
除法计算的源文件 div.c:
#include#include "head.h" double divide(int a, int b) { return (double)a/b; }
头文件 head.h:
#ifndef _HEAD_H #define _HEAD_H // 加法 int add(int a, int b); // 减法 int subtract(int a, int b); // 乘法 int multiply(int a, int b); // 除法 double divide(int a, int b); #endif
测试文件 main.c:
#include#include "head.h" int main() { int a = 11; int b = 28; printf("a = %d, b = %dn", a, b); printf("a + b = %dn", add(a, b)); printf("a - b = %dn", subtract(a, b)); printf("a * b = %dn", multiply(a, b)); printf("a / b = %fn", divide(a, b)); return 0; }
1.2 生成静态库
第一步:将源文件 add.c, div.c, mult.c, sub.c 进行汇编,得到二进制目标文件 add.o, div.o, mult.o, sub.o
# 1. 生成.o $ gcc add.c div.c mult.c sub.c -c # 提示头文件找不到, 添加参数 -I 重新头文件路径即可 $ gcc add.c div.c mult.c sub.c -c -I ./include/ # 查看目标文件是否已经生成 $ ls
第二步:将生成的目标文件通过 ar 工具打包生成静态库
# 2. 将生成的目标文件 .o 打包成静态库 $ ar rcs libmytest.a add.o div.o mult.o sub.o # add.o div.o mult.o sub.o在同一个目录中可以写成 *.o # 查看目录中的文件 $ ls
第三步:将生成的的静态库 libcalc.a 和库对应的头文件 head.h 一并发布
# 3. 发布静态库 1. head.h => 函数声明 2. libcalc.a => 函数定义(二进制格式)
静态库的使用
编译测试程序 main.c $ gcc main.c -o test /tmp/ccF94vUK.o:在函数‘main’中: main.c:(.text+0x3a):对‘add’未定义的引用 main.c:(.text+0x5c):对‘subtract’未定义的引用 main.c:(.text+0x7e):对‘multiply’未定义的引用 main.c:(.text+0xa0):对‘divide’未定义的引用 collect2: error: ld returned 1 exit status
上述错误分析: 编译的源文件中包含了头文件 head.h, 这个头文件中声明的函数对应的定义(也就是函数体实现)在静态库中,程序在编译的时候没有找到函数实现,因此提示 对‘xxxxxx’未定义的引用。 J解决方法:在编译的时将静态库的路径和名字都指定出来 -L: 指定库所在的目录 (相对或者绝对路径) -l: 指定库的名字,需要掐头 (lib) 去尾 (.a) 剩下的才是需要的静态库的名字
# 编译的时候指定库信息 -L: 指定库所在的目录(相对或者绝对路径) -l: 指定库的名字, 掐头(lib)去尾(.a) ==> mytest # -L -l, 参数和参数值之间可以有空格, 也可以没有 -L./ -lmytest $ gcc main.c -o test -L ./ -l mytest # 查看目录信息, 查看可执行程序是否生成 $ ls
# 执行生成的可执行程序 $ ./test a = 20, b = 12 a + b = 32 a - b = 8 a * b = 240 a / b = 1.666667



