发布时间:2023-02-14 12:30
在讨论静态和动态库之前,我们先回顾一下从源文件到生成可执行文件的过程。编译器需要4个步骤(预处理器、编译器、汇编、链接器)将源代码转换为可执行文件:
在gcc中,直接从main.c到main
gcc main.c -o main
处理器: 预处理器步骤删除文件中的所有注释,包括并扩展所有头文件,并用值替换所有宏。编译器: 编译然后获取预处理的代码并将其转换为汇编代码。
汇编代码: 汇编代码是一种人类可读的机器代码表示低级语言。汇编程序将汇编代码翻译成机器代码。
链接器: 链接步骤获取多个文件的所有目标代码或机器代码,并将它们链接到一个可执行文件中。
请注意,上图中的库实际上就是我们今天要讨论的内容。
编译 c 程序时,编译器生成目标代码(目标代码是尚未链接到完整程序的机器代码的一部分)。在生成目标代码之后,编译器还调用链接器。链接器的主要任务之一是编写库函数的代码(如 printf ()、 scanf ()、 sqrt ()…等)可用于您的程序。链接器可以通过两种方式完成这项任务,一种是将库函数的代码复制到目标代码(静态链接) ,另一种是进行一些安排,使库函数的完整代码不被复制,而是在运行时可用(动态链接)。
可以把静态库看作是位于 c 文件中的特定函数的集合,它们被编译成一个大文件,您可以随身携带并与任何文件一起使用,以解决特定的任务。静态库是文件编译成可执行文件时链接在一起的目标文件的集合。
优点:由于库代码是在编译时连接的,因此最终的可执行文件在运行时不依赖库,即不需要额外的运行时加载成本。静态库的一个主要优势是速度,即使现在也是首选。在静态库中不会有动态的符号查询。即使在今天,许多生产线软件仍然使用静态库。
缺点:创建了更大的二进制文件,需要更多的磁盘空间和主存。对于静态库中的任何变化(升级),都要重新编译主程序。
编译库文件
gcc -c libmylib.c -o libmylib.o
创建动态库
ar rcs libmylib.a libmylib.o
编译驱动程序
gcc -c driver.c -o driver.o
将已编译的驱动程序链接到静态库。-L传递了静态库的路径,-l传递了库名(lib* 中的 *)。
gcc -o driver driver.o -L. -lmylib
或者直接从源文件
gcc driver.c -L. -lmylib -o driver
运行驱动程序
./driver
优点:显著减小可执行程序的大小;如果更新之后认为与原始版本二进制兼容,则无需重新编译代码
缺点:与静态库相比,执行时间较慢;入伏哦库更改而未将库重新编译到内存中,则可能存在兼容性问题;当一个库的新版本与旧版本不兼容时,需要进行更改。
编译器选项: