动态库和静态库

一、编译四步骤

了解动态库和静态库之前,先了解动态库和静态库。

编译过程可以划分为四个阶段:预处理(Pre-Processing)、编译(Compiling)、汇编(Assembling)以及链接(Linking)。下面的四步内容不必深究,知道这么回事就行。

1.预处理

预处理主要做下面的几个操作:

(1)宏的处理

可以看下面的链接。

C++宏的作用-CSDN博客

(2)添加行号信息、文件名标识,便于调试

(3)删除注释

        等等,这步完成之后,生成.i文件。

2.编译

编译主要做下面的操作:

(1)语法分析,查看是否有语法错误

(2)生成汇编代码

等等,这步完成生成.s文件。

事实上,这一步骤最为消耗系统资源和时间。

3.汇编

汇编主要做下面的操作:

(1)将汇编指令翻译成机器指令,也就是二进制文件

等等,生成.o文件

4.链接

链接主要做下面的操作:

(1)合并各个文件

(2)地址回填

二、gcc命令

以hello.c源文件为例:

(1)只执行预处理,输出hello.i

 gcc -E hello.c

(2)只执行预处理、编译,输出hello.s

gcc -S hello.i

这步消耗时间,系统资源最大。

-S只执行预处理、编译。

(3)只进行汇编,输出hello.o,即目标文件。

gcc -c hello.s

-c只进行预处理、编译、汇编

(4)只进行链接,输出hello.out,即可执行程序。

gcc test.o

(5)一步到位,并且-o是将文件名改为后面参数的名字

gcc hello.c -o hello

(6)-I(大写的i)指定头文件路径

如果头文件和源文件不在同一级目录下,则需要加头文件的路径。

(7)-Wall,显示更多警告信息。

三、动态库和静态库

1.库的介绍和作用

库是一个二进制可执行的文件。库需要加载到内存中使用。

库的作用有:

1.库是已经写好的,成熟的,可以复用的功能代码,我们写的很多代码都是依赖于基础库。

2.提高代码移植效率,可以不用移植源码,直接移植库即可。

2.静态库和动态库的介绍和区别

静态库在程序编译时会被连接到目标代码中,把库直接加载到程序中,程序运行时将不再需要该静态库。每有一个可执行文件就需要一个静态库的载入。

动态库在程序编译时并不会被连接到目标代码中,在链接的时候,它只是保留接口,将动态库与程序代码独立,在程序运行时才被载入,因此在程序运行时还需要动态库存在。动态库可以在程序间共享,因此又称共享库。

因此,静态库相较动态库速度较快,但内存要求较高。动态相较速度较慢,但内存需求低。

3.制作静态库

1.制作编译源文件

例如,下面是我staticFile文件夹下的文件。

//add.c
int add(int value1,int value2)
{
    return value1+value2;
} 
//minus.c
int minus(int value1,int value2)
{
    return value1-value2;
} 

 查看如下:

动态库和静态库_第1张图片

 将add.c和minus.c两个文件编译,成为目标文件。运行下面的命令:

gcc -c add.c -o add.o
gcc -c minus.c -o minus.o

查看如下:

动态库和静态库_第2张图片

2.制作静态库文件

Linux的静态库文件格式为:lib+库名+.a。

运行下面的命令:

ar rcs libmymath.a add.o minus.o

查看如下: 

动态库和静态库_第3张图片

3.使用静态库

假如有一个源文件使用咱们制作的静态库。该源文件如下:

#include
int main()
{
    int value1=8;
    int value2=4;
    
    printf("value1+value2=%d\n",value1+value2);
    printf("value1-value2=%d\n",value1-value2);

    return 0;
} 

输入下面的命令:

gcc test.c libmymath.a -o test

得到了咱们的可执行程序test:

动态库和静态库_第4张图片

运行:

动态库和静态库_第5张图片

而且test生成后,我们可以将libmymath.a删除,test照常运行。

此时运行下面的命令:

gcc test.c libmymath.a -o test -Wall

可能会出现下面的警告:

动态库和静态库_第6张图片

至于说为什么是可能呢,因为我的没警告 ,上面的图是我从别人那q来的:

 但为了防止警告,还得加下面的内容:

再创建一个头文件,实际上这个头文件是库的配套产品,制作库的同时需要制作头文件,在使用时加上头文件,另外再输入gcc test.c libmymath.a -o test命令,完成最终的程序。

头文件如下:

#ifndef _MYMATH_H_
#define _MYMATH_H_

int add(int,int);
int minus(int,int);

#endif

程序源文件改为:

#include
#include"mymath.h"//多加了这一行
int main()
{
    int value1=8;
    int value2=4;

    printf("value1+value2=%d\n",value1+value2);
    printf("value1-value2=%d\n",value1-value2);

    return 0;
}

然后再编译执行,结果:

4.制作动态库

 1.制作编译源文件

因为动态库是运行时加载到内存的,因此动态库的地址不固定。为了生成与位置无关的代码,我们需要再编译时加上-fPIC。现文件夹下有下面的内容:

动态库和静态库_第7张图片

 输入下面的命令:

gcc -c add.c -o add.o -fPIC
gcc -c minus.c -o minus.o -fPIC

结果如下:

动态库和静态库_第8张图片

 2.制作动态库文件

Linux动态库的格式:lib+库名+.so

输入下面的命令:

gcc -shared -o libmymath.so add.c minus.c

3.使用动态库

因为动态库是运行时链接的,所以需要运行时指定动态库所在目录位置。因此,Linux中以设置环境变量来解决该问题。

临时方法:

export LD_LIBRARY_PATH=动态库路径

永久方法:

修改~/.bashrc文件,加入上面的语句。

gcc的可选项-l(小写的L),指定库名。-L,指定库文件路径。

注意库名是lib后面,.so之前的内容,这里是mymath。

输入下面的命令:

gcc test.c -o test -l mymath -L ./ -I ./

输入./test运行: 

你可能感兴趣的:(c++,开发语言)