库的作用:

  1. 分离编译
  2. 代码重用

分类:

分类作用后缀
静态库一个或多个.o目标文件归档在一个文件中.a
动态加载库没有main函数的可执行文件,接口复合API.so

C语言编译的流程:
在这里插入图片描述

1. 静态库的制作与使用

在这里插入图片描述

1.1 创建

文件举例:
calc.cpp

#include <iostream>
#include "calc.h"
using namespace std;
int main(){
    int a = _sub(10,2);
    int b = _plus(10,2);
    cout<<a<<" "<<b<<endl;
}

calc.h

#ifndef _CALC_H
#define _CALC_H

int _sub(int,int);
int _plus(int,int);

#endif

sub.cpp

#include<iostream>
#include"calc.h"
using namespace std;

int _sub(int a,int b){
    return a-b;
}

plus.cpp

#include<iostream>
#include"calc.h"
using namespace std;
int _plus(int a,int b){
    return a+b;
}
  1. 编译源文件
g++ -c plus.cpp sub.cpp
  1. 生成静态库
ar -rcs libmycalc.a plus.o sub.o

ar选项:

命令选项作用
r替换模块(replace)
c创建库(create)
s建立索引

1.2 使用

  • 链接静态库
g++ calc.cpp -o calc -L . -lmycalc

或者:

g++ calc.cpp -o calc ./libmycalc.a

如果少加参数会产生如下错误:
在这里插入图片描述
第一个错误是没有指定连接库,第二个错误是没有指定库的目录
注意:库一定要放在命令行的末尾

  • 测试
./calc
  • 结果
8 12

2. 动态库的制作与使用

在这里插入图片描述
关键字PIC(position independent code)
进程运行的虚拟地址空间:
在这里插入图片描述
静态库是把代码直接加到代码段(text区),而动态库是临时加载的,运行的时候再加载
在这里插入图片描述

2.1 创建

  1. 编译目标文件:
g++ -c -fPIC plus.cpp sub.cpp
  1. 生成动态库:
g++ -shared plus.o sub.o -o libCalc.so

以上两步可以合并为:

g++ -shared -fPIC -o  libCalc.so plus.o sub.o

2.2 使用

  1. 生成可执行文件
g++ -o calc calc.cpp -L. -lCalc

或者

g++ -o calc calc.cpp ./libCalc.so
  1. 测试

指定动态链接库位置

export LD_LIBRARY_PATH=动态链接库位置

执行

./calc
  • 结果
    在这里插入图片描述
    列出程序所需动态库连接:
    在这里插入图片描述

3. 动态库与静态库的区别

  • 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库,因此体积较大。
  • 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在,因此代码体积较小。
    在这里插入图片描述
    在这里插入图片描述

3.1 动态加载与静态加载的区别

  • 动态加载

1.灵活,可以在需要的时候进行加载,在不需要的时候进行卸载,这样可以不必占用内存。
2.可以在没有动态库时候发现,而不致程序报错。
3.加载程序中有条件才运行的库。
4.热更新,在不停止程序的前提下进行更新。
5.复杂一些,需要显示获得函数地址。

  • 静态加载

1.简单方便
2.没有找到动态库时,系统报错
3.加载运行很久的库

4. 总结

静态库、共享库与动态库编译链接使用比较:
在这里插入图片描述
静态库与动态库Make file比较:
在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐