0x01 C库简介
C语言提供了非内置的功能去执行一些常见计算机操作,例如:IO,内存管理,字符串操作等。这些库被定义成标准库,这样方便你进行编译和链接它们在你自己的程序中。
C standard Library 是由ANSI C制定的C标准库。(https://en.wikipedia.org/wiki/C_standard_library)
ANSI C 或者ISO C,以及我们熟悉的C90,C99,C11等都是C标准库的规范。(https://en.wikipedia.org/wiki/ANSI_C)
C POSIX Library 是为POSIX制定的C标准库。(https://en.wikipedia.org/wiki/C_POSIX_library)
POSIX 的全称是可移植的编程接口,是类Unix系统(System V,Berkeley Unix)间编程的规范,由IEEE计算机协会指定。(https://en.wikipedia.org/wiki/POSIX)
GUN C 则是包含了上述 C standard library 和 C posix library,旨在帮助程序员可以更好的在linux环境下进行开发,使得程序可以达到最大的可移植。(https://www.gnu.org/software/libc/manual/html_node/Introduction.html#Introduction)
0x02 GUN C 库使用规范
头文件引入规范
语法: #include "header" //引用自定义头文件 #include <file.h> //引用系统已经安装好的头文件 注意: 1,多次引用同一个头文件并没什么不妥 2,显式引用你所需要的所有的头文件,而不是依赖头文件之间的相互引用,这种依赖并不可靠 目的: 1,系统头文件定义了操作系统之间的编程接口,你引用系统头文件的目的是为了执行系统调用或者使用一些系统函数 2,自定义的头文件定义了你自己的程序之间的编程接口,你引用它们的目的是为了使你的程序尽可能的可维护,可扩展 内容: 头文件定义了一些类型,宏以及函数声明
详细参考:https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html#Header-Files
宏定义规范
依赖: 宏的实现依赖C标准中的预处理器(preprocessor) 分类: 1,文件包含 #include 2,条件编译:#if,#elif,#else,#endif,#ifdef 3,自定义宏和移除宏定义 自定义宏语法: 1,object-like 宏:#define <identifier> <replacement token list> 2,function-like 宏:#define <identifier>(<parameter list>) <replacement token list> 注意:自定义宏中 function-like 宏的 identifier 和后面的参数列表之间的 () 之间不能有空格 移除宏定义: 1,#undef <identifier> 字符替换操作符: 1,# 操作符会将所有的宏标识替换成一个字符串(包括各种引号和空格) 2,举例: #define str(s) #s str(p = "foo\n";) // outputs "p = \"foo\\n\";" str(\n) // outputs "\n" 字符拼接操作符: 1,## 操作符会将标识拼接到一起组成一个标识 2,举例: #define DECLARE_STRUCT_TYPE(name) typedef struct name##_s name##_t DECLARE_STRUCT_TYPE(g_object); // Outputs: typedef struct g_object_s g_object_t; 注意: 1,宏调用和调用一个函数没什么不同,可能宏会快一点
命名规范及保留字符
注意: 1,所有 GUN C 库中定义的类型名称,宏名称,变量名称,函数名称等都是保留字,个人程序应该去避免冲突 2,所有个人程序引用的外部库中的名称也属于保留字,个人应用程序应该去避免冲突 3,尽量避免冲突的好处是C编译器可以去尽可能的优化程序 4,以 _ 开头,或者以 __ 开头,或者以 _X(大写字符)开头都属于保留字 5,还有更多的类库保留字,详情请参考下面链接 建议: 1,在个人程序中使用项目标识作为各种名称的前缀是一个很不错的办法,Nginx就是这么做的
详细参考:https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names
功能测试宏
详细请参考官方文档:https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html#Feature-Test-Macros
GUN C库目录结构
参考官方文档:https://www.gnu.org/software/libc/manual/html_node/Roadmap-to-the-Manual.html#Roadmap-to-the-Manual
0x03 错误报告
GUN C Library 中各个函数在错误的时候都会返回相应的错误码,在个人程序中对一个有可能报错的操作应该去校验它的返回码是否正确。要使用所有这些错误码信息等相关错误机制你需要引入 error.h 头文件。
错误检测
1,大部分的库在出错的时候返回 -1, null, EOF 来表示出错 2,想要明确的知道具体错误的信息需要依靠全局变量 errno 3,errno 是可以被任意函数修改的,包括异步的信号处理都有可能会修改 errno 的值。大部分的函数在出错的时候都会去修改 errno 4,有些函数像 sqrt, atan 等在出错的时候完全返回一个合法的值,但是它们也会去修改 errno,所以你想要知道是否发生错误应该在 调用这类函数前先将 errno 设置为 0,然后去检测 errno 的值去发现错误 5,所有的错误码都有一个以 "E" 开头的宏定义标识,定义在 error.h 头文件中 6,所有的 errno 都是不会重复的,除了 EWOULDBLOCK 和 EAGAIN 7,errno 的值不一定非得和以 "E" 开头的各种宏定义的值一致,每个类库可以有自己的 errno 值
错误码
GUN C Library 库中所有的 errno 含义及其对应的宏定义标识列表请参考:https://www.gnu.org/software/libc/manual/html_node/Error-Codes.html#Error-Codes
错误消息内容
1,strerror 2,perror 上述俩函数是常用的根据一个 errno 获取对应的错误消息函数
其它相关函数列表请参考:https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html#Error-Messages