day02:静态库 和共享库(动态库)
c程序员的错误处理
环境变量和环境表
详细笔记如下:
一个操作系统是非常复杂的,提供非常多的系统函数,如何管理这些系统函数:比如:函数 a()究竟来自哪个.o件? 需要把所有的.o文件打包,打包成静态库或共享库
静态库(.a) 共享库(.so)
静态库和共享库的区别:
静态库是代码的一个归档,在使用静态库的时候,采用的复制代码的方式。
共享库是可执行文件的执行组成部分,在使用共享库时是采用提供代码在共享库的地址 给可执行文件的方式。
静态库和共享库的优缺点:
静态库的优点就是完全独立,代码链接后再运行时不再需要静态库的参与,同时效率稍高,缺点是 占用空间大,修改和维护不方便。
共享库的优点是 占用空间小,修改和维护方便,缺点就是不独立,运行时需要可执行文件和共享库同时参与,效率稍低
静态库的创建和使用步骤:
创建步骤:
1.写源文件.c,保存退出
2.编译源文件,生成xxx.o文件
gcc -c xxx.c
3.用ar -r 命令生成静态库文件.a
ar -r lib库名.a xxx.o
静态库文件有命名规范,以lib开头,以.a结束,中间是库名
调用步骤:
1.写调用的源文件.c,保存退出,这里要导入包含函数声明的头函数
2.编译连接源文件和静态库文件,有三种方式:
2.1 直接连接法 gcc test.c 库文件名(libtest.a)
gcc test.c libmyku.a
2.2 双L连接法 gcc test.c -l库名 -L库所在的路径
库名不包括lib 和.a gcc test.c -lmyku -L.
2.3单l连接法 需要先配置环境变量LIBRARY——PATH,把库文件所在的路径配置进来,然后用l就可以了
export LIBRARY_PATH=.
gcc test.c -lmyku
注意:提供库文件的程序员,必须同时提供头文件。
共享库的创建和使用步骤:
创建步骤:
1 编写源文件,保存退出
2 编译源文件,生成.o文件 gcc -c -fpic xxx.c
3 生成共享库文件 gcc -shared xxx.o -olibmyku.so
ps:共享库是可执行文件的一部分
使用步骤和静态库完全一样,但是要配置环境变量
注意:共享库在运行时会参与进来,因此在运行时,必须保证能找到共享库,需要配置环境变量LD_LIBRARY_PATH.
指令:export LD_LIBRARY_PATH=.
Unix系统提供了一系列的共享库和头文件,代码出自共享库,函数的函数声明出自头文件,指令:ldd a.out 就可以查看相关的库文件都有哪些
C程序员的错误处理-错误处理不可怕,是 程序员必须面对的,是软件编程的一个组成部分
不是所有的错误都可以处理。但可以处理的错误必须考虑如何处理。
后期的计算机语言(C++/JAVA)都是采用异常机制进行错误处理(Exception),但是C语言没有异常机制,C程序员用返回值标识错误。
关于返回值,有以下4种情况:
1 如果函数的返回值是int ,并且返回的数据不可能是负数 ,返回-1,代表出错了,其他数据正常返回。
2.如果函数的返回值是int,并且返回的数据可能是负数,用返回0 代表没有错,用返回 -1 代表出错,数据用 指针返回
3 如果函数的返回值是指针,用NULL 代表出错,个别函数也用 (void*)-1 代表出错。
4.如果函数不可能出错,或不需要考虑错误处理,返回值不着任何的改变
以上始终情况,只是c程序员的一般情况,也有特例存在
C官方提供了一个变量和三个函数,用于错误的显示和处理;
c语言存储的都是错误编号,而如果想知道是什么错误,必须查看编号对应的错误信息,错误编号存在外部全局变量errorno,错误编号转错误信息的函数有:
strerror() - 传入错误编号 返回错误信息,不打印
perror() -自动打印errno 对应的错误信息并换行() (没有发生的错误无法查看)
printf("%m") 自动打印errorno对应的错误信息 ,了解
如果代码出错了,会改变errno的值,记录错误编号,如果代码没有出错,errno是不会改变的,因此不能用errorno判断是否出错。errorno是用来记录错误信息的,返回值是用来判断时候出错的。
c程序员处理错误的一般流程:
用返回值判断时候出错,如果出错,调用perror()打印错误信息,并进行错误分支的代码编程。
注:不是所有的函数都支持errorno,有些函数就没有使用errno,比如线程相关的函数都没有使用
环境变量和环境表
程序员如何操作环境,命令也是程序员写的程序
环境表是字符指针数组,char* arr[],是所以环境变量在内存中的首地址。字符指针数组可以用char**(二级指针)表示。很多时候环境表就是使用二级指针表示。
extern char** environ;就可以直接获得环境表的首地址。
environ也是也各外部的全局变量,但是在声明时没有加上extern,因此需要调用者自己加。extern代表全局变量来自于其他文件中。
environ一般都不直接参与指针的移动,而是用一个局部变量 代替environ进行指针的移动,因为environ是所有的程序公用的。
指针的算数运算(加法和减法)移动的字节数由 指向的数据类型的大小决定,指向int,移动sizeof(int)字节(加1的情况下)。