GNU C library学习笔记

一个误解引入:

#define _XOPEN_SOURCE 并不是简单的宏定义,引入它会打开一些编译特性,它是使程序符合系统环境的不可缺少的部分。

GNU C library的介绍

1、glibc 所实现全部或者部分规范下的功能有

  • ISO C: The international standard for the C programming language.
  • POSIX: The ISO/IEC ArrayArray45 (aka IEEE 1003) standards for operating systems.
  • Berkeley Unix: BSD and SunOS.
  • SVID: The System V Interface Description.
  • XPG: The X/Open Portability Guide.

关系与区别:

如果只需要 ISO C 的功能,可以在编译时使用 -ansi 选项。glibc 实现了全部的 ISO C 功能。POSIX 是 ISO C 的超集,它额外的包括了 file system interface primitives、device-specific terminal control functions、process control functions。Berkeley Unix 实现了前两者多数功能,源于 4.2 BSD、4.3 BSD, and 4.4 BSD Unix 系统(一般称为 Berkeley Unix)以及 SunOS (基于 4.2 BSD 但是又实现了 System V 的部分功能),它额外的包括了 symbolic links、the select function、BSD signal functions、sockets。SVID 是 System V Interface Description,也就是描述 AT&T Unix System V operating system 的一份文档,某种意义上是 POSIX 的超集,但是没有已有的 Unix 实现了其全部功能,glibc 也仅仅实现了其部分功能。它额外实现的功能包括 the methods for inter-process communication(IPC)、shared memory、hsearch、drand48 系列函数、fmtmsg、一些其他的数学函数。XPG(The X/Open Portability Guide)描述了什么样的系统满足类 Unix 系统的基本需要,glibc 服从该要求。

程序中,为了实现上述功能需要定义对应的宏。如第二个功能POSIX,应定义 _POSIX_SOURCE。类似的有 _BSD_SOURCE、_SVID_SOURCE、_XOPEN_SOURCE。也就是说:
#define _XOPEN_SOURCE
是为了可以使用 The X/Open Portability Guide 的功能。

2、如何开启某种标准下 glibc 的功能。

前面提到可以利用 -ansi 仅仅使用 ISO C 以内的功能。其他的通过定义 macro 实现条件编联,实现方式分两种,可以在 .c 里面 #define,或者用 -D 把这个 macro 传递给 gcc。例如:

1)在cc命令中指定,如:cc -D _POSIX_SOURCE file.c
2)将源程序的第一行设置为:#define _POSIX_SOURCE 1

为了实现 POSIX 的功能,应定义 _POSIX_SOURCE (_POSIX_C_SOURCE 决定实现的 POSIX 标准类型,如 1、2、>3 实现的功能逐步增多)。类似的有 _BSD_SOURCE、_SVID_SOURCE、_XOPEN_SOURCE。为了处理大文件产生的问题,应定义 _LARGEFILE_SOURCE,又比如 64 位文件系统应定义 _LARGEFILE64_SOURCE。_ISOCArrayArray_SOURCE 允许使用 ISO C ArrayArray 的标准。_GNU_SOURCE 将允许使用全部的 glibc 的功能。

#define _GNU_SOURCE
#include 
#include 

int
main( int argc, char *argv[] )
{
  printf( "%s\n%s\n%s\n", argv[0],
          program_invocation_short_name,
          program_invocation_name ) ;

  return 0 ;
}

该例子给出了如何使用非 ISO C 的 program_invocation_(short_)name 变量(程序名带或者不带路径)的例子。使用 _REENTRANT 和 _THREAD_SAFE 时保证使用对应的函数。

一些笔记:注意的点

1、 头文件里面某些函数的实现使用 macro 做到的,理由是一般这样会更快。但是不需要区别他们,因为一般定义了同名的函数,如 abs(int) 既有函数定义也有 macro 定义,使用 & 操作时,由于 macro 调用时不能匹配到 () 因此仍然能取到函数的地址。如果需要显式的调用函数可以用 () 将函数名包围,如 (abs)(3),又或者使用 #undef abs 将定义过的 macro 取消。

2、 ISO C 允许重复 #include 头文件,但是 glibc 使用了 #define #ifndef 等预处理器命令避免了同一头文件重复装载,因此可以放心的 #include glibc 的头文件。

3、 除了 ISO C 定义的一些保留字,由于 glibc 实现了一些额外的功能,建议不要使用可能与之冲突的一些命名方式。

4、. error handling 模型,这种依赖于全局变量 errno 的做法 ms 被 BS bs 了 -.-b 指责的原因是不能处理多线程倒是文档中解释了如何处理 signal handling 时 errno 的处理(先备份,再修改以免丢失),但是如果忘了这样做可能会把一些潜在的错误覆盖掉,其错误的定义在 errno.h 文件中。可使用 string.h 里面的 strerror( int errno ) 获得该 errno 下的一个字符串解释,但是有更简单的函数,如 perror( const char * ) 输出指定字符串后加上一个冒号和空格再输出错误解释(errno.h)。有一些功能更强大的函数 strerror_r 将字符串写入指定的缓存(多线程时需要),另外为了使得输出更统一(符合 GNU Coding Standard),在 error.h 中定义了一些更加方便的函数,如 error 系列 err 系列,在解析文件时可以用到的 error_at_line 系列、warn 系列。注意 error 函数可以指定一个调用 exit 的值,
这样就不会返回了,但是可以让其返回增大 error_message_count。

文章参考自:http://www.sudu.cn/info/html/edu/code/20071121/7296.html

你可能感兴趣的:(C,lib)