1

处理字符值的正确方法是什么,当转换为无符号字符时,字符值介于 {INT_MAX + 1 ... UCHAR_MAX} 之间,其中 UCHAR_MAX 大于 INT_MAX。

int is_digit(char c) {
    unsigned char uchar = c;
    if(uchar > INT_MAX)
        return MAYBE;
    return isdigit((int)uchar) ? YES : NO;
}
4

2 回答 2

1

唯一的方法UCHAR_MAX将大于INT_MAX如果你在一台机器上使用sizeof(int) == 1; , wherechar的位数与int. 在这些机器上,UCHAR_MAX= UINT_MAXINT_MAX

在 32 位(或更高版本)机器上,这不太可能成为问题。只要变量中的值c来自文本源,就没有我知道的文本编码会导致溢出。即使是“UTF-32”也只会激活低 21 位。(实际上,由于我们正在讨论奇数系统,我应该说这适用于sizeof(int)= 1 和CHAR_BIT≥ 22 的机器。☺)

如果在这样的机器is_digit()上仍然传递了一个c大于的参数INT_MAX那么它不是来自文本源。未定义的行为是将非字符数据放入char变量的结果,这将始终是程序员所做的事情,而不是实现导致的事情。

有一个系统可能会出现问题:16 位char和,并且系统使用了可以设置高位int的 16 位字符代码(例如UTF-16)。如果是这种情况,正是出于这个原因,实现将plain 定义char为已签名是理所当然的。使用char签名后,它将提升为(签名)int并可以安全地传递给is*()函数族;使用charunsigned 时,它将提升到并且强制转换为已签名可能是未定义的。unsignedintint

在这样的系统上,您的代码确实被破坏了,但这将是您自己的错,因为完全不必要的转换unsigned char和危险的(在这个系统上)强制转换(int)uchar

总结一下:在具有sizeof(int) == 1它的系统上,实现的责任是确保每个代码点在存储在char变量中时都可以安全地传递给ctype.h函数(需要int参数)。这总是可以做到的。如果您将某些内容存储在char不是代码点的变量中并将其传递给,is*()那么未定义行为的责任就在于您自己和您自己。

于 2012-02-02T16:11:18.517 回答
0

Unicode 字符集(这是最常用的)具有从 0 到 0x10ffff 的字符代码。因此,字符代码大于 INT_MAX 的唯一可能int是 16 位类型(或特别是小于 22 位)。如果是这种情况,那么您根本无法将字符代码存储在int.

如果int是 32 位类型(或至少 22 位),则字符代码在转换为int.

于 2010-06-28T22:28:06.100 回答