库
自己的理解:遵循了程序员的模块编程思想
:为了对功能的增删更方便
:为了查改错误更方便
:版权
百度百科:定义
一般是指编译器提供的可在c源程序中调用的函数。可分为两类,一类是c语言标准规定的库函数,一类是编译器特定的库函数。
由于版权原因,库函数的源代码一般是不可见的,但在头文件中你可以看到它对外的接口。
Linux c语言分文件编程编程演示
方法一:把主函数和被调函数分开
编译的时候gcc calculate.c calculateH.c 两个文件一起编译
编译器会有警告,甚至结果会出错
分开前
operation.c
#include <stdio.h>
int addition(int a,int b)
{
return a + b;
}
int subtraction(int a,int b)
{
return a - b;
}
int multiplication(int a,int b)
{
return a * b;
}
float divide(int a,int b)
{
return (float)a / b;
}
int main ()
{
int a;
int b;
int result;
float resultfloat;
printf("请输入两个数\n");
printf ("数一:");
scanf("%d",&a);
printf ("数二:");
scanf("%d",&b);
result = addition(a,b);
printf("%d+%d=%d\n",a,b,result);
result = subtraction(a,b);
printf("%d-%d=%d\n",a,b,result);
result = multiplication(a,b);
printf("%d*%d=%d\n",a,b,result);
resultfloat = divide(a,b);
printf("%d/%d=%f\n",a,b,resultfloat);
system("pause");
return 0;
}
分开后
calculateH.c
int addition(int a,int b)
{
return a + b;
}
int subtraction(int a,int b)
{
return a - b;
}
int multiplication(int a,int b)
{
return a * b;
}
float divide(int a,int b)
{
return (float)a / b;
}
calumniate.c
#include <stdio.h>
int main ()
{
int a;
int b;
int result;
float resultfloat;
printf("请输入两个数\n");
printf ("数一:");
scanf("%d",&a);
printf ("数二:");
scanf("%d",&b);
result = addition(a,b);
printf("%d+%d=%d\n",a,b,result);
result = subtraction(a,b);
printf("%d-%d=%d\n",a,b,result);
result = multiplication(a,b);
printf("%d*%d=%d\n",a,b,result);
resultfloat = divide(a,b);
printf("%d/%d=%f\n",a,b,resultfloat);
system("pause");
return 0;
}
编译:gcc calculate.c calculateH.c
两个文件一起编译
会有警告(warning)
方法二 :多添加自制头文件
加多一个头文件calculate.h 里面是calculateH.c函数声明
int addition(int a,int b);
int subtraction(int a,int b);
int multiplication(int a,int b);
float divide(int a,int b);
calculate.c添加头文件
#include "calculate.h"
为什么是" "号而不是<>:
<>:默认去/usr/include/或者/usr/local/include/找头文件
“ ” :会先从当前目录找头文件,找不到再到默认路径找,再找不到就报错
编译指令还是:gcc calculate.c calculateH.c
没有警告,运行结果正确。
静态库
静态函数库:在执行前(编译时)就加入到目标程序中。
优点:1、静态库已经在编译时打包到运用程序加载快,
2、发布的时候程序无需提供静态库,因为已经编译在app(application)中,移植方便。
缺点:1、链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
2、更新、部署、发布麻烦。
制作静态库
1、原材料:xxx.c 或 xxx.cpp
将c文件生成 .o
指令:gcc a.c b.c -c :运行该指令就会生成 a.o 和 b.o 文件
也可以gcc calculateH.c -c :只生成calculateH.
2、原料:xxx.o
ar rcs 静态库名字,原料
ar rcs libtest.a a.o b.o :打包两个只生成一个libtest.a
或者ar rcs libtest.a a.o :只打包a.o生成libtest.a
文件名前面lib三个字母一定要有!!!
r、c、s、分别是什么含义
可以直接在命令行输入:ar
r[ab][f][u] - replace existing or insert new file(s) into the archive :替换现有文件或将新文件插入存档(主要)
[c] - do not warn if the library had to be created :如果必须创建库,不警告
[s] - create an archive index (cf. ranlib) :创建存档索引
使用静态库编译:ar rcs calculate.a calculateH.o
gcc calculate.c -lcalculate -L ./ :出错
这里的-L:编译时从-L指定的路径去找库,gcc默认地从/usr/local/lib, /usr/lib中搜索库文件
调试
1. objdump -a calculate.a :查看静态文件适用于哪种系统(多少位)
查询结果:没发现毛病
In archive calculate.a:
calculateH.o: file format elf64-x86-64
rw-r--r-- 0/0 1584 Dec 31 16:00 1969 calculateH.o
2. 试着编译gcc calculate.c calculate.a :结果编译成功
加上路径也成功gcc calculate.c /home/abc/xxx/calculate.a
- [root@Xecho mycode]# gcc -o 2 2.c /usr/lib/libm.a
[root@Xecho mycode]#
它告知gcc:在编译2.c时,加入位于/usr/lib中的libm.a库(C数学库)。C库文件默位
于/usr/lib, /usr/local/lib系统目录中; gcc默认地从/usr/local/lib, /usr/lib中搜索库文件。
指定库文件的绝对路径比较麻烦,有一种简化方法:
[root@Xecho mycode]# gcc -o 2 2.c -lm
看到这里终于想起编译时可以砍头去尾:但是头尾一定要有,ar rcs calculate.a calculateH.o 忘记添加lib
动态库
动态库比静态库更常用
动态函数库:是在程序执行时动态(临时)由目标程序调用。
优缺点跟静态库相反。
优点:程序小,简洁,多程序可共用,节省内存,更新动态库,不用重新编译可执行文件
缺点:运行慢,发布需要提供动态库
制作动态库
1、gcc calculateH.c -c -fpic :生成calculateH.o文件
-fpic :用于编译阶段生成目标文件就得使用,用来生成位置无关码
PIC,全称Position Independent Code
位置无关码:位置无关代码是指代码无论被加载到哪个地址上都可以正常执行。
2、gcc -shared calculateH.o -o libcalculate.so :生成so文件
-shared :指定生成动态库
或者一步到位
gcc -shared -fpic calculateH.c -o libcalculates.so :直接生成so文件
!!!注意 .so 文件名必须以 lib 开头
使用动态库编译:gcc calculate.c -lcalculates -L ./ calculates
运行calculates 的时候发现会报错
./calculates: error while loading shared libraries: libcalculates.so: cannot open
shared object file: No such file or directory
原因是:可执行程序运行时才去调用动态库,默认地会从/usr/lib/文件夹下面找
解决方法:
1、可以把动态库libcalculates.so拷贝到/usr/lib/下面
但是不建议:因为这样会使/usr/lib/更乱
2、 暂时配置环境变量:export LD_LIBRARY_PATH=/home/hgs/learningDocument
只适用于当前窗口
3、写一个shell脚本:
a.创建 vi start.sh
1 export LD_LIBRARY_PATH=/home/hgs/learningDocument
2 ./calculates
b.给start.sh 可执行权限 sudo chmod +x start.sh
4、修改环境变量
a. 打开环境变量配置文件sudo vi ~/.bashrc
b.在文件末尾添加export LD_LIBRARY_PATH=/home/hgs/learningDocument
c.使配置文件生效source ~/.bashrc
最后:运行结果
abc@ubuntu:~/learningDocument$ ./calculates
请输入两个数
数一:4
数二:5
4+5=9
4-5=-1
4*5=20
4/5=0.800000
动态函数库和共享函数库是一个东西
共享函数库的命名规则
libxxx.so.0.1.2 :
lib:代表共享库
xxx:库名
so:共享库固定后缀
0:版本号
1:次版本号
2 :发行版本号