Section outline

  • <ctype.h> – 字符处理(Character Handling)

    在标准 C 中,<ctype.h> 中提供的所有函数都接受一个 int 类型参数。然而,传入的值必须是可以用 unsigned char 表示的值EOF。若传入其他值,行为是未定义的

    C89 引入了**区域设置(locale)**的概念。默认情况下,C 程序运行在 "C" 区域,除非调用了 setlocale 函数(或实现默认区域不是 "C")。在 "C" 区域中,<ctype.h> 的函数行为与 C89 之前一致。

    当选择了除 "C" 以外的区域时,某些字符类别的判定可能会扩展。例如,在西欧地区运行的实现中,可能将带变音符(如 äêñ)的字符视为字母。因此,字符 ä 是否使 isalpha 返回真,是由当前区域设置定义的。

    许多实现使用的字符表示比宿主字符集所需的位数更多,例如支持 7 位 ASCII 的 8 位字符系统。这样可以利用未使用的位扩展字符集。此外,C 程序员可以将 char 当作小整数使用,存入任何能表示的位模式。

    但当 char 中的内容不是本机字符集的一部分时,不应将其传入 <ctype.h> 中的函数,除非当前区域允许。即使允许,结果仍是实现定义的。同时,还应注意 char 是否为有符号类型,因为值为 0x80 的 8 位 char,在 signed 与 unsigned 情况下行为会不同。

    标准 C 要求 <ctype.h> 中的函数必须作为实际函数实现。但也允许它们以宏的形式实现,前提是宏是安全的(即每个参数只被求值一次)。如果需要使用函数版本,可以通过 #undef 取消对应宏。

    建议<ctype.h> 中的测试函数在返回 true 时的实际值是实现定义的。因此,不应用作算术比较,只应用于逻辑判断

    标准 C 保留了所有以 isto 开头、后跟小写字母(然后是任意标识符字符)的函数名,以备将来扩展库函数。

    以下函数具有区域相关行为

    • isalpha, isblank, isgraph, islower, isprint, ispunct, isspace, isupper, toupper, tolower

    C89 之前,以下函数在许多实现中也通过此头文件提供:

    • isascii, toascii, iscsym, iscsymf
      但这些函数不属于标准 C 支持的函数

    C++ 注意事项:对应的标准 C++ 头文件为 <cctype>


    字符分类函数(Character Classification Functions)

    isalpha 函数
    使用 isalpha 替代如下代码:

    if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
    

    因为在某些字符集(如 EBCDIC)中,大小写字母在内部编码上不一定是连续的

    isblank 函数
    由 C99 引入。

    islower, isupper 函数
    同样参考 isalpha 的说明。


    字符大小写转换函数(Character Case Mapping Functions)

    tolowertoupper 函数
    在非 "C" 区域中,大写转小写的映射不一定是一对一的
    例如,大写字母可能被映射为两个小写字母,或者可能根本没有小写形式toupper 同理。


    <errno.h> – 错误处理(Errors)

    早期的 errno 被声明为 extern int,但标准 C 要求它是一个
    该宏可以展开为对同名函数的调用。标准中,errno 被定义为可修改的 int * 类型左值
    例如:errno 可以定义为 *_Errno(),其中 _Errno() 是一个返回 int * 的函数。

    errno 使用 #undef 试图访问底层对象的行为是未定义的

    许多标准库函数在检测到某些错误时会将 errno 设为非零值,且该值必须为正数
    标准 C 明确规定:库函数不负责将 errno 重置为 0,因此不能依赖其清除行为

    通常,errno 的宏值以 E 开头。虽然各系统之间对错误名的拼写和含义不统一,但 C89 仅定义了两个:

    • EDOM(数学域错误)

    • ERANGE(结果超出范围)

    C99 新增:

    • EILSEQ(非法多字节序列)

    标准兼容实现可定义其他以 E 加数字或大写字母开头的宏。例如:

    E2BIG    // 参数列表太长
    EACCES   // 权限被拒绝
    EAGAIN   // 暂时无法分配资源
    EBADF    // 错误的文件描述符
    EEXIST   // 文件已存在
    ENOMEM   // 内存不足
    ENOTDIR  // 非目录
    EPIPE    // 管道已破裂
    ...
    

    完整列表可见于原文,或参考实现的 <errno.h>

    参见:C11 添加的“边界检查接口”附录中可能对该头文件提出的要求(如宏 __STDC_LIB_EXT1__)。

    C++ 注意事项:对应的标准 C++ 头文件为 <cerrno>


    <fenv.h> – 浮点环境(Floating-Point Environment)

    该头文件由 C99 引入。

    标准 C 保留所有以 FE_ 开头、后接大写字母的宏名,用于将来在此头文件中添加新宏。

    C++ 注意事项:对应的标准 C++ 头文件为 <cfenv>


    <float.h> – 浮点类型特性(Characteristics of Floating Types)

    该头文件通过一系列宏定义目标系统的浮点类型特性,其值多为实现定义的

    截至 C17,大部分宏已由 C89 定义,少数新增:

    • C99 新增:DECIMAL_DIG, FLT_EVAL_METHOD

    • C11 新增:FLT_DECIMAL_DIG, DBL_DECIMAL_DIG, LDBL_DECIMAL_DIG,以及
      FLT_HAS_SUBNORM, DBL_HAS_SUBNORM, LDBL_HAS_SUBNORM,
      FLT_TRUE_MIN, DBL_TRUE_MIN, LDBL_TRUE_MIN

    虽然许多系统采用 IEEE-754 浮点格式,但在 C89 制定时,还有其他三种格式被广泛使用,C89 对这些格式也提供支持。

    标准 C 为 FLT_ROUNDS 宏定义了值 -1 到 3,其它值表示实现定义的舍入方式。

    标准 C 为 FLT_EVAL_METHOD 宏定义了值 -1 到 2,其它负值表示实现定义行为。
    该宏的值可能影响浮点常量的求值(详见“浮点常量”相关说明)。

    C++ 注意事项:对应的标准 C++ 头文件为 <cfloat>


    <inttypes.h> – 整数类型的格式转换(Format Conversion of Integer Types)

    该头文件由 C99 引入。

    标准 C 保留所有以 PRISCN 开头、后跟小写字母或 X 的宏名,用于未来在此头文件中扩展。

    C++ 注意事项:对应的标准 C++ 头文件为 <cinttypes>


    <iso646.h> – 替代拼写(Alternative Spellings)

    该头文件由 C95 引入,定义了一些操作符的英文拼写替代形式,例如:

    • and 替代 &&

    • or 替代 ||

    • not 替代 !

    C++ 注意事项:对应的标准 C++ 头文件为 <ciso646>,这些宏在标准 C++ 中被当作关键字处理。


    <limits.h> – 数值限制(Numerical Limits)

    该头文件通过一系列宏定义目标系统中整数类型的数值特性,其值大多是实现定义的

    几乎所有宏都已在 C89 中定义,少数例外如下:

    • C99 新增:LLONG_MIN, LLONG_MAX, ULLONG_MAX

    C++ 注意事项:对应的标准 C++ 头文件为 <climits>