GCC基础
GCC处理流程
.h 或 .c 或 .cpp
通过预处理器得到预处理后的源代码 .i
.i
通过编译器得到汇编代码 .s
.s
通过汇编器得到目标代码 .o
.o
通过链接器得到可执行文件 .exe 或 .out
实例
1
2
3
4
5
6
7
gcc test.c -E -o test.i 注意-o指的是生成输出文件 后面的是输出文件名称
这里生成了预处理后的源代码
gcc test.i -S -o test.s
这里生成了汇编代码
gcc test.s -s -o test.o 注意这里是小s
这里生成了目标代码
如果test.c没有用到外部文件可以直接执行.o
静态库
命名规则:
- Linux:
libxxx.a
lib
前缀是固定的
xxx
是名字
.a
后缀固定
- Windows:
libxxx.lib
静态库制作
gcc获得
.o
文件1
gcc -c xxx.c xxx.c
将
.o
文件打包,使用ar工具1 2 3 4
ar rcs libxxx.a xxx.o xxx.o r - 将文件插入备存文件中 c - 建立备存文件 s - 索引
静态库特点:
静态库优点:
- 静态库被打包到应用程序中加载速度快。
- 发布程序无需提供静态库, 移植性好 。
静态库缺点:
- 消耗系统资源,浪费空间和内存。因为函数相关的所有的库都被打包进可执行文件了。
- 更新,发布,部署较为麻烦。更新以后需要重新编译:库是被复制到可执行文件中去了,如果某个库更新了,则与它相关的所有可执行文件都需要重新编译。
静态库对函数库的链接是放在编译时期完成的。
动态库
命名规则
Linux:
libxxx.so
lib
前缀是固定的xxx
是名字.so
后缀固定在linux下是一个可执行文件
Windows:
libxxx.dll
动态库制作
gcc得到
.o
文件,需要添加-fpic 或 -fPIC
参数得到和位置无关的代码1
gcc -c -fpic/-fPIC xxx.c xxx.c
gcc 得到动态库
1
gcc -shared xxx.o xxx.o -o libxxx.so
注意事项
在include的头文件路径和执行文件不一致的时候需要加上 -I
参数指定头文件目录
在动态库的路径和执行文件路径不一致的时候需要加上-L
参数指定动态库文件目录
动态库存在需要设置环境变量的情况。这里不赘述
使用示范
动态库静态库相同
1
2
3
假设路径不同
gcc 执行文件名 -o 输出文件名 -I 头文件目录 -L 动态库目录 -l 动态库名称 注意不是文件名称是动态库名称
gcc main.c -o main -I ./include/ -L ./lib/ -l calc
动态库特点:
动态库优点:
- 动态库只有一份, 可以实现进程间资源共享(共享库)。
- 更新,部署,发布简单。
- 可以控制何时加载动态库。(可以在链接载入时完全由程序员在程序代码中控制。)
动态库缺点:
- 加载速度比静态库慢。
- 发布程序时需要提供依赖的动态库。
动态库把对一些库函数的链接载入推迟到程序运行的时期。
区别与联系
二者的不同点在于代码被载入的时刻不同。 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大。 动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。
不同的应用程序如果调用相同的库,那么在内存中只需要有一份该动态库(共享库)的实例。 静态库和动态库的最大区别,静态情况下,把库直接加载到程序中,而动态库链接的时候,它只是保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度,和降低程序的耦合度。 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要动态库存在。