GCC动态库与静态库的使用

一、库的定义

所谓库文件,读者可以将其等价为压缩包文件,该文件内部通常包含不止一个目标文件(也就是二进制文件)。

值得一提的是,库文件中每个目标文件存储的代码,并非完整的程序,而是一个个实用的功能模块。例如,C 语言库文件提供有大量的函数(如 scanf()、printf()、strlen() 等),C++ 库文件不仅提供有使用的函数,还有大量事先设计好的类(如 string 字符串类)。

库文件的产生,极大的提高了程序员的开发效率,因为很多功能根本不需要从 0 开发,直接调取包含该功能的库文件即可。并且,库文件的调用方法也很简单,以 C 语言中的 printf() 输出函数为例,程序中只需引入 <stdio.h> 头文件,即可调用 printf() 函数。

调用库文件为什么还要牵扯到头文件呢?首先,头文件和库文件并不是一码事,它们最大的区别在于:

头文件只存储变量、函数或者类等这些功能模块的声明部分;
库文件才负责存储各模块具体的实现部分;
读者可以这样理解:所有的库文件都提供有相应的头文件作为调用它的接口。也就是说,库文件是无法直接使用的,只能通过头文件间接调用。

头文件和库文件相结合的访问机制,最大的好处在于,有时候我们只想让别人使用自己实现的功能,并不想公开实现功能的源码,就可以将其制作为库文件,这样用户获取到的是二进制文件,而头文件又只包含声明部分,这样就实现了“将源码隐藏起来”的目的,且不会影响用户使用。

事实上,库文件只是一个统称,代指的是一类压缩包,它们都包含有功能实用的目标文件。要知道,虽然库文件用于程序的链接阶段,但编译器提供有 2 种实现链接的方式,分别称为静态链接方式和动态链接方式,其中

采用静态链接方式实现链接操作的库文件,称为静态链接库;
采用动态链接方式实现链接操作的库文件,称为动态链接库;
在 C、C++ 实际开发过程中,除了可以使用系统库文件外,我们还可以根据实际需要,手动创建静态链接库或者动态链接库。

出自:
GCC 编译 C(C++)静态链接库(gcc -L、gcc -l)和动态链接库(gcc -fPIC -shared)的创建和使用

·动态库与静态库的区别

1. 静态库:

静态库是在链接时被完整地复制到可执行文件中的库文件。当程序运行时,静态库的代码被加载到内存中,与程序一起执行。

优点

静态库的使用简单,只需要将库文件链接到可执行文件即可,无需其他依赖。
静态库的执行速度相对较快,因为代码已经被完整复制到可执行文件中,无需动态加载和解析。

缺点

静态库的体积较大,会增加可执行文件的大小。
如果多个可执行文件都使用同一个静态库,会导致重复的代码复制,浪费存储空间。

2. 动态库:

动态库是在程序运行时才被加载和链接的库文件。当程序需要使用动态库的函数时,动态库才会被加载到内存中,然后函数被执行。

优点

动态库的体积相对较小,不会增加可执行文件的大小。
多个可执行文件可以共享同一个动态库,减少了重复代码的复制,节省了存储空间。
动态库的更新和升级更加方便,只需要替换库文件即可,无需重新编译可执行文件。

缺点

动态库的使用相对复杂,需要在运行时动态加载和链接库文件。
动态库的执行速度相对较慢,因为需要动态加载和解析库文件。

二、库的创建与使用

1. 准备工作

动态库和静态库都是在.o文件的基础上创建的,所以需要通过gcc得到.o文件

Ⅰ 准备.h头文件和对应的.c文件

如:
在A1.c里面声明一个print1(int arg)函数

#include <stdio.h>
void print1(int arg){
	printf("A1 print arg:%d\n",arg);
}

在A2.c里面声明一个print2(char *arg)(.c文件个数任意,只要头文件中包含到)

#include <stdio.h>
void print2(char *arg){
	printf("A2 printf arg:%s\n", arg);
}

声明一个头文件A.h

#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif

声明一个测试文件test.c用于测试使用库

#include <stdlib.h>
#include "A.h"
int main(){
	print1(1);
	print2("test");
exit(0);
}

在这里插入图片描述

Ⅱ 生成.o文件

gcc -c [文件名.c]

注:若要后面生成动态库,-c 后面必须添加"-fpic"如

gcc -c -fpic A1.c A2.c

否则要报错

在这里插入图片描述

2. 生成库

Ⅰ 静态库

ar -rc libafile.a A1.o A2.o

Ⅱ 动态库

gcc -shared A1.o A2.o -o libofile.so

在这里插入图片描述

3. 使用库

Ⅰ 静态库

gcc -o test test.c libafile.a

测试:
在这里插入图片描述

Ⅱ 动态库

gcc -o test test.c libofile.so

在这里插入图片描述
找不到对应的.so 文件。
这是由于 linux 自身系统设定的相应的设置的原因,即其只在/lib and /usr/lib 下搜索对应的.so 文件,故需将对应 so 文件拷贝到对应路径:

sudo cp 你的路径/libsofile.so /usr/lib

再次执行./test,即可成功运行
在这里插入图片描述

三、实例

编写x2x函数和x2y函数(功能自定),main函数代码将调用x2x和x2y ;将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小。
将x2x、x2y目标文件用 ar工具生成1个 .so 动态库文件, 然后用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录文件的大小,并与之前做对比

1. 创建文件

x2x:
在这里插入图片描述
在这里插入图片描述
x2y:
在这里插入图片描述
在这里插入图片描述

main:

在这里插入图片描述

2. 生成.o文件

在这里插入图片描述

3. 生成静态库

在这里插入图片描述

4. 生成动态库

通过gcc -shared可以把静态库链接为动态库
在这里插入图片描述

4. 编译为可执行文件

在这里插入图片描述

5.测试

Ⅰ 测试链接静态库的main

在这里插入图片描述
使用ls命令查看文件大小

ls -l file_name

在这里插入图片描述
可知链接静态库的main文件大小为16.08kb

Ⅱ 编译链接动态库的main2

① 先将liboxx.so复制至usr/lib/

在这里插入图片描述

② 编译main2

在这里插入图片描述

③ 测试

在这里插入图片描述
在这里插入图片描述
大小为16.01kb
可以看出采用动态库编译出来的可执行文件比静态库可执行文件小

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值