處理字符值的正確方法是什麼?當轉換爲無符號字符時,字符值落在{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;
}
處理字符值的正確方法是什麼?當轉換爲無符號字符時,字符值落在{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