编译过程理解动态库与静态库,先要理解程序编译过程在进行编译的过程中程序会分为5个阶段,下面分开来解释预处理阶段主要解决字符替换如:宏的字符替换,头文件的声明复制到源文件编译主要是编译器进行它会进行词法分析、语法分析、语义分析、代码优化等复杂操作。汇编主要是将汇编指令翻译成二进制机器码,但是此时还没有链接库所以它是残缺的无法正常执行链接主要任务拼图组装解决地址引用链接器 (ld) 将所有的目标文件以及库文件组合在一起生成最终的可执行程序。合并段将各个 .o 文件的代码段、数据段合并统一排布在内存空间中。符号解析找到未定义的符号。例如 main.o 调用了 printf但 printf 的代码不在 main.o 里链接器会去 C 标准库libc.a 或 libc.so里找到 printf 的实现并将其合并进来。重定位修正地址。因为 .o 文件合并后函数和变量的最终内存地址发生了变化链接器会修正所有调用指令中的地址使其指向正确的内存位置。输入文件.o 文件、库文件输出文件可执行文件Linux 下默认为 a.out 或指定名称GCC 命令gcc main.o -o main库所以只有链接过后才是一个可以正常执行的程序静态库静态库是在程序编译链接阶段,链接器将静态库中被调用的代码直接复制到最终生成的可执行文件其不依赖外部的库文件,部署简单,运行时不需要查找库但是会将生成的可执行文件体积变大,在库更新时需要重新编译整个程序,多个程序进行会在内存生成多个相同的库代码副本动态库在编译时,可执行文件中只保留库函数的引用当需要调用时,查询动态库绑定到系统内存使用动态库链接的可执行文件体积小,相同的程序不需要重复占用内存部署相对复杂 容易陷入Dependency Hell 依赖地狱问题如何制作自己的库?静态库在制作自己的库之前我们首先需要先有一段封装好的code简单封装个sum求和// sum.c#includeSUM.hintsum(int*a){intsum;for(inti0;isizeof(*a);i){sum*(ai);}returnsum;}// SUM.h#ifndef_SUM_H#define_SUM_H//这里给出声明intsum(int*a);#endif下面采用GCC封装一下gcc-csum.c-osum.o#将.c编译为二进制.o文件ar crs libsum.a sum.o#将sum.o封装到静态库中ar t libsum.a#列出当前库中包含的.o文件如下: $ ar t libsum.a sum.o那么现在静态库就封装好了动态库依旧是上面的代码gcc-csum.c-osum.o-fPIC#fPIC表示产生的二进制与内存无关 可以提高兼容性gcc--shared-fPIC-olibsum.so sum.o#将.o封装进动态库使用自己的库使用静态库静态库就比较简单了将我们的libsum.a 链接到我们的main中gcc main.c-omain.exe-lsum-L./#链接静态库使用动态库libsum.so在使用的时候需要保证动态库要么在系统库目录中,要么为其配置环境变量gcc main.c-omain.exe-lsum-L./#-L指定头文件位置 -l指定库位置如果动态库与静态库重名时优先使用动态库