C++中什么經常會運用到char類型,也會將char類型作為循環語句的循環條件,但往往這里最容易出現錯誤,容易出現溢出,進入死循環。這里我們就來簡單介紹下為什么會出現這種情況。
首先,了解下char類型的取值范圍:
char分為無符號(unsigned)和有符號(signed)兩種:
無符號(unsigned)的取值范圍:0~255;
有符號(signed)的取值范圍為:-128~127.
一般我們常用char來聲明一個變量,編譯器默認為有符號的,即范圍為:-128~127.
常見溢出問題:
知道了char類型的取值范圍后,就容易理解為什么會出現溢出了。出現溢出的地方很多都是因為將char類型的變量作為了循環語句的條件部分,這樣就很容易出現溢出,這里講解一下char類型的自增情況。
一般作為循環條件時,char類型往往被賦值了int類型,如char i = 0,然后i進行自增。
當i是無符號型時,取值范圍為-128 ~ 127,當i=127后再進行自增的時候,這時i就不是等於128了,而是等於-128;當i= -128,再進行自減的時候就不是等於-129,而是等於127.
當i是有符號型的時候,取值范圍為0 ~ 255,當i = 255時,再進行自增,這時i=0,而不是等於256;當i=0,進行自減的時候i= 255,而不是-1.
這是因為char型對於有符號型,前24位永遠和倒數第8位一樣,對於無符號型,前24位永遠為零。
造成上面的結果的原因:
當為有符號型時,當i = 127時,二進制為:0....0 0111 1111,然后加1后,按照上面的原理,變為:1....1 1000 0000,結果i = -128;當i=-128時,減1,二進制變為:0....0 0111 1111,結果i = 127.
當為無符號時,當i=255時,二進制為:0....0 1111 1111,加1后,按照上面的原理,變為:0....0 0000 0000 ,結果為i= 0;當i = 0時,減1,二進制為:0...0 1111 1111,結果為255.
下面通過一個實例來說明:
#define s8 char static int k = 0; void func() { s8 i = 0; for(i = 0; i < 128; i++) { k += i&3; } printf("k = %d\n", k); }
這里很多人可能會動筆就計算,算得 k= 192,但結果是錯的。
原因:注意i為一個char類型,且為有符號型,並被賦初值0,這里當i = 127的時候,程序會正常進行,然后i自增,變為-128,最后還是滿足條件,程序並不會終止,這樣就出現了char類型的溢出,程序進入死循環。此時,要么改變循環中的條件,改為:i < 127;或者將i的類型改為int型。