C标准库源码解剖(2):错误报告errno.h

    errno.h在/usr/include下,定义了存放错误码的全局变量errno,及错误码EDOM,ERANGE,EILSEQ。它包含了/usr/include/bits下的bits/errno.h头文件。bits/errno.h不是标准C库中的头文件,在Linux中它为错误码提供数值定义,对标准C中指定的错误码EDOM,ERANGE,EILSEQ定义具体的数值。
    bits/errno.h如下:

/* bits/errno.h: 错误报告常量  Linux专用的版本(/usr/include/bits/errno.h)  */
#ifdef _ERRNO_H
# undef EDOM
# undef EILSEQ
# undef ERANGE
# include <linux/errno.h>
/* Linux没有ENOTSUP错误码  */
# define ENOTSUP EOPNOTSUPP
/* 早期的Linux版本也没有ECANCELED错误码  */
# ifndef ECANCELED
#  define ECANCELED	125
# endif
/* 支持健壮锁机制的错误码  */
# ifndef EOWNERDEAD
#  define EOWNERDEAD		130
#  define ENOTRECOVERABLE	131
# endif
# ifndef __ASSEMBLER__
/* 获取全局变量errno的地址的函数 */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
#  if !defined _LIBC || defined _LIBC_REENTRANT
/* 当使用线程时,errno是一个单线程变量 */
#   define errno (*__errno_location ())
#  endif
# endif /* !__ASSEMBLER__ */
#endif /* _ERRNO_H */
#if !defined _ERRNO_H && defined __need_Emath
/* 这个虽然丑陋,但内核并不是完全干净的。在__need_Emath被定义的情况下,我们必须只定义
   EDOM,EILSEQ和ERANGE的值 */
# define EDOM	33	/* 参数不在数学函数能接受的范围内  */
# define EILSEQ	84	/* 非法的字节顺序,在翻译多字节字符序列时遇到的编码错误  */
# define ERANGE	34	/* 数学函数的结果超出范围  */
#endif /* !_ERRNO_H && __need_Emath */

    标准C的errno.h头文件如下:

/* ISO C99 Standard: 7.5  错误报告	 <errno.h> */
#ifndef	_ERRNO_H
/* 预处理器如果只需要EDOM和ERANGE的定义,不需要其他任何的错误码,
    则它会定义__need_Emath宏 */
#ifndef	__need_Emath
# define _ERRNO_H	1
# include <features.h>  /* 定义了一些表示编译选项的宏 */
#endif
__BEGIN_DECLS
/* 从依赖于系统的文件中获取错误码常量,这个依赖于系统的文件将会测试__need_Emath
    和_ERRNO_H */
#include <bits/errno.h> 
#undef	__need_Emath
#ifdef	_ERRNO_H
/* 定义全局变量errno,除非它被bits/errno.h定义成了一个宏。
    在GNU中,它是一个单线程的变量。有这个重新定义时errno宏仍然可以工作,但现在
    它将成为一个没有原型的函数声明,可能会触发一个-W-Wstrict-prototypes警告 */
#ifndef	errno  
extern int errno; 
#endif
#ifdef __USE_GNU
/* 程序被调用时会带有这些变量,它们在基于ARGV[0]的值来启动程序(仅当你使用GNU ld程序)
    时会自动被设置 */
extern char *program_invocation_name, *program_invocation_short_name;
#endif /* __USE_GNU */
#endif /* _ERRNO_H */
__END_DECLS
#endif /* _ERRNO_H */
 /* 有一些<bits/errno.h>中定义了error_t作为一个枚举类型,这样在调试器里打印error_t的
     值时就可以显示其名称。即使前面包含了<bits/errno.h>,有时我们还是需要定义一下 */
#if defined __USE_GNU || defined __need_error_t
# ifndef __error_t_defined
typedef int error_t;  
#  define __error_t_defined	1
# endif
# undef __need_error_t
#endif

    解释:
    (1)C标准规定了必须定义错误码EDOM,EILSEQ,ERANGE,其值可以由系统自行指定,在Linux中它们分别为33、84、34。
    (2)EDOM表示参数不在数学函数能接受的范围内;EILSEQ表示非法的字节顺序,在翻译多字节字符序列时遇到的编码错误;ERANGE表示数学函数的结果超出范围。程序产生相应错误时全局变量errno会保存对应的错误码。
    (3)__BEGIN_DECLS/__END_DECLS宏用来表示数据结构及函数原型声明的开始和结束。这类似于MFC中的BEGIN_MESSAGE_MAP/END_MESSAGE_MAP。
    还有两个错误处理函数perror和strerror。perror在stdio.h中定义,用于打印错误码及其消息描述;strerror在string.h中定义,用于获取错误码对应的消息描述。这两个函数在解析相应头文件时再进行分析。

转载于:https://my.oschina.net/abcijkxyz/blog/723226

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值