处理ctype.h整数溢出

时间:2010-06-28 22:05:18

标签: c99 integer-overflow ctype

处理字符值的正确方法是什么,当转换为无符号字符落在{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;
}

2 个答案:

答案 0 :(得分:1)

如果您使用UCHAR_MAX的计算机,则INT_MAX的唯一方式是sizeof(int) == 1,其中char的位数与int的位数相同。在这些计算机上,UCHAR_MAX = UINT_MAXINT_MAX

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

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

有一个可能出现问题的系统:16位charint,系统使用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时字符代码不会溢出。