2010-06-28 136 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*(),那麼責怪未定義的行爲就是你自己的&。