2010-06-28 103 views
1

处理字符值的正确方法是什么?当转换为无符号字符时,字符值落在{INT_MAX + 1 ... UCHAR_MAX}之间,其中UCHAR_MAX大于INT_MAX。处理ctype.h整数溢出

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

你在哪里UCHAR_MAX大于'INT_MAX'? – 2010-06-28 22:09:11

+1

我必须将所有代码都放在我正在使用的机器上吗? – 2010-06-28 23:11:12

回答

0

Unicode字符集(这是最常用的)具有从0到0x10ffff的字符代码。因此,如果int是16位类型(或者具体小于22位),则字符代码的唯一可能性大于INT_MAX。如果是这种情况,那么你根本不能在int中存储字符代码。

如果int是32位类型(或至少22位),那么在投射到int时,字符代码不会溢出。

+0

您始终可以使用utf-8和或char数组来存储单个代码点。 无论如何。字符串文字由字符组成,而ctype.h函数不能在字符上使用。编写C99的人必须考虑这个角落案例。 – 2010-06-28 23:09:19

+0

@Elite:这是一个角落案件?你知道任何使用完整的21位Unicode代码点的系统(即以UTF-32存储字符串)并且有16位int吗? – Guffa 2010-06-29 00:04:32

+0

Unicode与任何事物无关。关注这两个事实。你有一个角色,它有一个价值(ZOMG!它甚至可能是负面的)。像isdigit这样的函数可能不会接受你的价值。最后 - ctype.h中的函数不可靠。 – 2010-06-29 07:26:48

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无符号,它将推广到unsignedint并且转换为签名int可能是未定义的。

在这样的系统中,你的代码确实是坏了,但是这将是你自己的完全不必要的转换到unsigned char和危险的(这个系统)故障(int)uchar

总结:在与sizeof(int) == 1系统中,实施的责任,确保每一个代码点,存储在char变量时,可以安全地传递给ctype.h函数(预计int参数)。这可以总是完成。如果你在char变量中存储了一些不是代码点的东西,并将其传递给is*(),那么责怪未定义的行为就是你自己的&。