C语言中的静/动态库文件
起因
之前一直对 .a
、.so
文件的存在犯迷糊。现在想来,之所以当时会有不解,是因为从没用 C 语言写过项目,顶多只是语法的测试,以及一些算法实现。现在略微搞明白些了,于是有了这篇总结。
编译
当尝试在终端敲入 gcc -o test test.c
时,其实就是告诉编译器,请把我的代码(test.c)编译成一个可执行文件(test)。在这个短短过程中,代码经历了四个阶段,分别是:1. 预处理阶段 2. 编译阶段 3. 汇编阶段 4. 链接阶段。
不同阶段有不同的事儿要做,从头至尾如下:
- 预处理阶段:1. 删除注释 2. 宏替换 3. 条件编译 4. 将头文件放到 .c 文件中,最后生成 .i 文件;(
gcc -E -o test.i test.c
) - 编译阶段:将 C 语言翻译成汇编语言,生成 .s 文件;(
gcc -S -o test.s test.i
) - 汇编阶段:将汇编翻译成机器语言,生成 .o 文件;(
gcc -o test.o -c test.s
) - 链接阶段:将 .o 文件链接生成可执行文件。(
gcc -o test test.o
)
在上述四个阶段中,.i 和 .s 都是文本文件,你可以打开来看看里面都写着啥。后两个阶段是二进制文件,你想打开看,那就看一堆乱码。也并非束手无措,可以用 objdump
命令反汇编。像下面这样:
root@hui:make$ objdump -xd test.o
test.o: file format elf64-x86-64
test.o
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000
...
函数库
前面唠叨那么多,就是想引出 .o 文件。
函数库,顾名思义:里边存放了一堆供程序员使用的函数。其实不但有函数名、函数对应的实现代码,还有链接过程中所需的重定位信息。
函数库分为静态库(.a 文件)和动态库(.so)文件。 Linux 中,标准的 C 函数库放在 /usr/lib 目录下;而用户,也可以根据自生需求,建立自己的用户函数库。
这里需要注意,由于函数库来自于 .o 文件,也就是说,是一堆二进制文件构成,你看不到里面的库函数代码。所以库函数该怎么用呢?这就体现了头文件中的重要性。所以 .h 文件与 .c 最好是要分开写。
静态库
静态库是一些 .o 目标文件的集合,以 .a 结尾,在程序链接的时候使用。链接器会将程序中使用到的函数代码从库文件中拷贝到可执行文件里边,完成链接后,可执行文件不需要静态库也能独立执行。
静态库的创建方式:
$ ar rcs lib库文件名.a 目标文件1.o 目标文件2.o 目标文件3.o ...
参数说明:
- r 表示将 .o 的目的文件加入到静态库中;
- c 表示创建静态库;
- s 表示生成索引。
创建的库文件名字前面最好加上前缀 lib ,方便编译器找到它。(你可以认为这是一种规范)
静态库的使用方式:
$ gcc -o 可执行文件 源码.c -I[头文件目录] -L[库文件目录] -l[库文件