一、C高级 - 代码复用
对于C
这种面向过程的语言来说,使用的函数库,
而对于java
这种面向对象的语言来说,使用的则是类库
参考:
《操作系统 - 静态库和动态库,进程间通信 之 共享内存》
《C高级 - 静态链接 与 动态链接》
一、代码复用的方式
函数代码的复用方式有如下几种:
- 以源码形式复用
- 以
.o
文件复用 - 以库形式复用
1. 以源码形式复用
如何复用
在自己的程序中,需要调用到什么函数,就将函数源码所在的
.c
、.h
拷贝到自己C
工程中,
然后和自己的程序的.c
、.h
一起编译,然后得到可执行程序
对于编译器来说,不管是自己写的代码,还是复用的源码,都是一样的,并没有区别,
只不过复用的源码不一定是我们自己写的
以源码形式复用情况并不少见,以源码形式复用时,我们可以将源码直接称为“源码库”,
当然源码有源码的好处,好处就是,你可以通过源码了解代码的具体实现,但是源码的缺点也是明显的
使用源码有三个缺点:
- (1)缺点1:“源码可见”不利于版权保护
- (2)缺点2:我们自己要清楚,我们要使用的函数在哪个
.c
中,
但是如果源码中.c
、.h
非常多的话,这就有些麻烦了 - (3)缺点3:编译
c
源码很耗费时间
如果程序的代码量非常庞大的话,是非常耗费编译时间的,
本来当一个程序写大之后,就已经要耗费不少的编译时间了,
如果再加入大量的库源码在里面,这将会更加的拉长编译时间
正是因为以上原因,所以源码库虽然不少见,但是也并不多见,
比如stm32
单片机的标准外设库和HAL
外设库,就是以源码形式提供的,但凡提供源码,必然是开源的
2. 以二进制.o文件复用
如何复用
事先将要被复用的
.c
全部编译为对应的.o
,你要调用什么函数,就将这个函数所在的
.o
复制到自己的工程中,
然后与自己程序的.o
链接到一起,就得到了可执行程序
优点:
- (1)
.o
为二进制文件,文本编辑器是无法正常显示二进制文件的,
打开后为一堆的乱码,提供.o
的话,可以有效的避免了源码外泄的问题 - (2)要复用的源码,事先早就被编译为了
.o
,只需要链接即可,有效的节省了编译时间
缺点
当要复用的
.o
非常多时,比如有几十个、甚至几百个时,
要记住那些函数在那些.o
中的话,其实是很困难的事情
基于这样的原因,大家就想着能不能自动识别呢,比如我在程序中调用到了什么函数,
就自动去识别这个函数在哪个或者那几个.o
中,然后自动去链接这些.o
,于是就有了真正意义上的“函数库”
真正的“库”其实就是就是将.o
进行打包,做成库文件,
链接库时,库会自动识别我们程序中调用的函数在哪些.o
中,然后自动找到那些.o
,然连接到我们的程序中
3. 库的原理
原理很简单,先将要复用的源码.c
编译为对应的.o
,然后再将所有的.o
打包做成“库”文件
使用时,直接链接“库文件”即可,在程序中调用了某个函数,
链接库文件时会自动帮我搜索这个函数在库中的哪些.o
中,然后就链接库中这些.o
做成真正的库文件有如下好处:
- (1)不需要公开源码,维护了版权
- (2)不需要浪费额外的编译时间,因为事先就编译好了,只需要链接即可
- (3)也不需要人为的挑选.o,链接库时会自动的搜素。
库分为两种,静态库 和 动态库。静态库和动态库文件的尾缀,与编译器和操作系统都有关。
静态库
总的来说,静态库的尾缀是由平台来决定的
Windows
平台:静态库的结尾为.lib
Linux
平台:静态库的结尾为.a
但实际上静态库文件是以.a
结尾还是.lib
结尾,与编译器也有关,
比如gcc
编译器,不管编译得到静态库是运行在Windows
上还是运行在Linux
上,
使用gcc
做出的静态库文件都是以.a
结尾的
动态库
动态库名字的尾缀,基本上只与平台有关,
Windows
平台:动态库的结尾为.dll
Linux
平台:动态库的结尾为.so