处理字符值的正确方法是什么,当转换为无符号字符落在{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;
}
答案 0 :(得分:1)
如果您使用UCHAR_MAX
的计算机,则INT_MAX
的唯一方式是sizeof(int) == 1
。 即,其中char
的位数与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)其中可以设置高位。如果是这种情况,那么实现就应该将普通char
定义为签名,正是出于这个原因。如果char
已签名,则会将其提升为(已签名)int
,并可安全地传递给is*()
系列函数; char
无符号时会将其提升为 unsigned
int
,并且可能未定义对已签名int
的强制转换。
在这样的系统上,你的代码确实被破坏,但是这将是你自己的错误,完全不必要的转换为unsigned char
和危险的(在这个系统上)转换{{ 1}}。
总结:在具有(int)uchar
的系统上,实现有责任确保每个代码点在存储在sizeof(int) == 1
变量中时可以安全地传递给char
函数(期望ctype.h
参数)。这可以始终完成。如果你在一个不是代码点的int
变量中存储了一些内容并将其传递给char
,那么未定义行为的责任就在于你和你自己。
答案 1 :(得分:0)
Unicode字符集(常用的最大字符集)具有0到0x10ffff的字符代码。因此,字符代码大于INT_MAX的唯一可能性是int
是16位类型(或特别是小于22位)。如果是这种情况,那么您根本无法在int
中存储字符代码。
如果int
是32位类型(或至少22位),则转换为int
时字符代码不会溢出。