dbm数据库源代码分析(4):头文件部分(续)

来源:互联网 发布:a 寻路算法 js 编辑:程序博客网 时间:2024/05/16 11:47

   (7)proto.h:dbm例程的所有函数原型声明。包括内部接口和gdbm的用户接口。ndbm和dbm的兼容性实现也要用到这里的各个函数。这些函数的功能在具体的源代码解剖时会有详细说明。注意一些老式的非标准的C编译器中函数声明不能带参数列表,而标准的C编译器中函数声明必须带参数列表。为了兼容性,这里把函数的参数列表arg(包括函数名后面的括号)抽离出来定义成宏__P(arg),当编译器是标准编译器时(用标准C编译器内部定义的__STDC__宏来指定),__P(arg)被展开成arg,从而带参数列表。当编译器是非标准编译器时,__P(arg)被展开成(),从而不带参数列表。

   (8)ndbm.h:ndbm用户要包含的头文件。包含dbm_store操作的参数标识、datum结构、DBM结构、ndbm的所有用户接口声明,其中dbm_error和dbm_clearerr是用宏来定义的。

   (9)dbm.h:dbm用户要包含的头文件。包含datum结构、dbm的所有用户接口声明。

   (10)gdbm.proto和gdbm.proto2:编译时会合并成gdbm.h头文件,这是gdbm用户要包含的头文件。其中gdbm.proto2只包含了一个用户接口声明,其余都在gdbm.proto中(记录错误码的全局变量在gdbmerrno.h中,编译时会复制到gdbm.h中)。包含了各个操作的参数标识、datum结构、GDBM_FILE结构、gdbm的所有用户接口声明。注意其中的预编译格式
#ifdef __cplusplus
  extern "C" {
#endif

//一段代码,或者一系列函数原型声明

#ifdef __cplusplus
}
#endif
   这里__cplusplus是C++编译器中的内部定义的宏,C编译器中没有这个宏。这个格式的含义是:如果这是一段C++的代码(即用C++编译器来编译),那么加入extern "C"{...}处理其中的代码。即用C语言的方式来处理其中的代码。这主要是因为C++和C对产生的函数名字的处理是不一样的。C语言中没有重载函数的概念,所以C编译器编译的程序里,所有函数只有函数名对应的入口。而由于 C++语言有重载函数的概念,如果只有函数名对应入口,则会出现混淆。所以C++编译器编译的程序,应该是用函数名加参数类型列表来对应到入口,有时还包括返回类型等(从其生成的汇编代码中可以看出来,用gcc试试就可以知道了)。当我们在C++中要使用一个用C语言编写的库时,编译时是使用C++的方式来处理你的代码中用到的C函数,但是实际上链接的库文件却是用C的方式来处理函数的,这样经常会出现链接过不去的错误,因为链接器找不到函数。上面的extern "C"就是告诉C++编译器,这是一个用C写成的库文件,请用C的方式来链接它们。总之,当我们用C语言开发项目时,若希望用户在老式的非标准的C编译器,或者在C++中也能使用它们时,特别注意在导出的头文件中要使用__P宏、_cplusplus宏、extern"C"等。

 

 

   (11)getopt.h:包含了getopt、getopt_long、getopt_long_only函数,以及一个内部使用的函数_getopt_internal。getopt用来解析命令行的选项,在POSIX对它有详细的规范。它处理短选项,即“-c value“的格式,c是单个字符的短选项名,value是这个选项关联的值,多个短选项可以合并在一块(从而可有多个字符,但每个字符都是一个选项)。循环调用getopt就可以依次得到每个选项。getopt返回agrv数组中的下一个选项字符,遇到未知选项时,getopt返回问号(?),并把它保存到optopt中;遇到需要关联值的选项但未提供关联值时,getopt返回冒号(:)。外部变量optarg保存当前处理的选项的关联值(如果有的话);optind保存第一个非选项的索引;遇到未知选项时opterr会变成非零值,getopt就会向stderr打印一条错误信息;未知选项保存在optopt中。对GNU版本的getopt,在扫描命令行时,每处理完一个选项,就会重写argv数组,把所有非选项都集中在一起,到最后处理完所有选项后,argv数组只会保存各个非选项的字符串,从argv[optind]开始可以访问这些非选项的字符串。
   getopt_long和getopt_long_only是GNU对getopt的扩展,它支持处理长选项,即“--string=value”,string是长选项名(是一个字符串),value是其关联的值。
   getopt系列函数现在已经成为了C函数库的一部分,在Linux等现代的类UNIX系统中都有提供。getopt在<unistd.h>中 。作为扩展的getopt_long、getopt_long_only等在<getopt.h>中,且使用时必须包含有#define _GNU_SOURCE,还需要用到struct option结构。这里提供getopt.h及其源代码实现getopt.c只是为了向后兼容(因为以前的UNIX系统可能并没有提供这些设施)。因此这里并不准备对它们进行解剖。

 

原创粉丝点击