处理字符值的正确方法是什么,当转换为无符号字符时,字符值介于 {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;
}
处理字符值的正确方法是什么,当转换为无符号字符时,字符值介于 {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;
}
唯一的方法UCHAR_MAX
将大于INT_MAX
如果你在一台机器上使用sizeof(int) == 1
; 即, wherechar
的位数与int
. 在这些机器上,UCHAR_MAX
= UINT_MAX
≥ INT_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*()
函数族;使用char
unsigned 时,它将提升到并且强制转换为已签名可能是未定义的。unsigned
int
int
在这样的系统上,您的代码确实被破坏了,但这将是您自己的错,因为完全不必要的转换unsigned char
和危险的(在这个系统上)强制转换(int)uchar
。
总结一下:在具有sizeof(int) == 1
它的系统上,实现的责任是确保每个代码点在存储在char
变量中时都可以安全地传递给ctype.h
函数(需要int
参数)。这总是可以做到的。如果您将某些内容存储在char
不是代码点的变量中并将其传递给,is*()
那么未定义行为的责任就在于您自己和您自己。
Unicode 字符集(这是最常用的)具有从 0 到 0x10ffff 的字符代码。因此,字符代码大于 INT_MAX 的唯一可能int
是 16 位类型(或特别是小于 22 位)。如果是这种情况,那么您根本无法将字符代码存储在int
.
如果int
是 32 位类型(或至少 22 位),则字符代码在转换为int
.