处理ctype.h整数溢出
处理字符值的正确方法是什么?当转换为无符号字符时,字符值落在{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;
}
Unicode字符集(这是最常用的)具有从0到0x10ffff的字符代码。因此,如果int
是16位类型(或者具体小于22位),则字符代码的唯一可能性大于INT_MAX。如果是这种情况,那么你根本不能在int
中存储字符代码。
如果int
是32位类型(或至少22位),那么在投射到int
时,字符代码不会溢出。
您始终可以使用utf-8和或char数组来存储单个代码点。 无论如何。字符串文字由字符组成,而ctype.h函数不能在字符上使用。编写C99的人必须考虑这个角落案例。 – 2010-06-28 23:09:19
@Elite:这是一个角落案件?你知道任何使用完整的21位Unicode代码点的系统(即以UTF-32存储字符串)并且有16位int吗? – Guffa 2010-06-29 00:04:32
Unicode与任何事物无关。关注这两个事实。你有一个角色,它有一个价值(ZOMG!它甚至可能是负面的)。像isdigit这样的函数可能不会接受你的价值。最后 - ctype.h中的函数不可靠。 – 2010-06-29 07:26:48
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
和危险的(这个系统)故障投(int)uchar
。
总结:在与sizeof(int) == 1
系统中,实施的责任,确保每一个代码点,存储在char
变量时,可以安全地传递给ctype.h
函数(预计int
参数)。这可以总是完成。如果你在char
变量中存储了一些不是代码点的东西,并将其传递给is*()
,那么责怪未定义的行为就是你自己的&。
你在哪里UCHAR_MAX大于'INT_MAX'? – 2010-06-28 22:09:11
我必须将所有代码都放在我正在使用的机器上吗? – 2010-06-28 23:11:12