Char和int 一樣,都有有符號和無符號之說。即unsigned char和signed char。
1.C語言中我們用的char默認到底是有符號還是無符號的呢?
對於不同的教材會有不同的答案,其實有無符號都是自己電腦的編譯器決定的。注意:我的電腦默認是有符號的,以下實例都是按我的電腦默認的程序)
2. 有)無符號 char類型的取值范圍。
我們知道char類型所占據的空間內存一般是1個字節8位),signed char和unsigned char當然也是占1個字節8個位數。但是和int類型一樣,它們的取值范圍是有區別的。
Unsigned char類型的取值范圍是:0~255
Signed char類型的取值范圍是:-128~127
其值在范圍內時,會被正常處理,但是超過范圍就會發生我們所說的溢出。但是要注意的是,在范圍之內也並不意味著它就是可打印的字符。
1. 來看一下unsigned char類型的溢出問題
關於上界溢出
十進制
二進制
值
254
1111 1110
254
255
1111 1111
255
256
?
?
257
?
?
關於下界溢出
十進制
二進制
值
2
0000 0010
2
1
0000 0001
1
0
0000 0000
0
-1
?
?
-2
?
?
我們已經說過了unsigned char 的取值范圍是0~255,通過上述兩個表格:
在上界中254,255都能正常表示,那256和257它們不在計算機分配的范圍之內,它們是溢出了,那問號處的值應該怎麼表示呢?
同樣的,在下界中,0,1和2都在范圍之內,能正常表示,-1和-2很明顯溢出越界了,那怎麼表示呢?
2.再來看一下signed char類型的溢出問題
關於上界溢出
十進制
二進制
值
126
0111 1110
126
127
0111 1111
127
128
?
?
129
?
?
關於下界溢出
十進制
二進制補碼形式)
值
-127
1000 0001
-127
-128
1000 0000
-128
-129
?
?
-130
?
?
我們也已經知道了signed char的取值范圍是:-128~127.
在上界中,126和127在范圍之內,都能正常顯示值。但是128和129呢?
在下界中,-127和-128在范圍之內,都能正常顯示值。但是-129和-130呢?
1.程序實例驗證一下signed char中溢出的數字的值求signed char溢出中的問題)
#include <stdio.h> main() { signed char a=126,b=127,c=128,d=129; printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d); }
#include <stdio.h> main() { signed char a=-127,b=-128,c=-129,d=-130; printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d); }
從上述兩個程序中,我們不難得出以下結論的表格數據。
2.給出signed char溢出問題表格的答案:
關於上界溢出
十進制
二進制
值
126
0..0 0111 1110
126
127
0..0 0111 1111
127
128
1..1 1000 0000
-128
129
1..1 1000 0001
-127
關於下界溢出
十進制
二進制補碼形式)
值
-127
1..1 1000 0001
-127
-128
1..1 1000 0000
-128
-129
0..0 0111 1111
127
-130
0..0 0111 1110
126
注:0..0 表示24個0,1..1表示24個1
3.解析
從上述兩個表格中可以看到,不管是否超過上下屆,不管是負數還是正數,每增加減少)一個單位,就直接在二進制表示的最後一位上加減)1個單位。
並且相加和相減時,都先不看前24位,如果倒數第8位變為1,則前面24位全部設置為1,該數被解釋為負數;如果倒數第8位變為0,則前面24位全部設置為0,該數被解釋為正數。
我們來分別看看。
1)126和127
126和127是范圍之內的數字,他們的值是遵從規則的。所以他們的值也是126和127,並沒有越界。
2)128
從程序實驗和上表的結論中,我們得出了128的值竟然是-128.128這個數字是越界的數字,是127+1。
這時會在127的最後8位上加1,也就是在0..0 0111 1111的後8位0111 1111上加1,變為1000 0000。倒數第8位變成了1,所以前24個位也全部變為1,所以該數被表示為負數。它的值為 -1*2^7+0=-128。
根據負數的值在計算機中是以補碼的形式存儲的理論,也就是說1000 0000是補碼,即:-128在計算機中是以1000 0000存儲的,-128的原碼是1000 0000補碼)減1,再取反,結果還是1000 0000原碼)。
3)129
129和128的取值也是一樣的道理。129是127+2或者128+1,拋開前24位不說,它的二進制為1000 0001,倒數第8位為1,所以前24位也為1,並且為負數。所以它的值表示為: -1*2^7+1=-127.
根據負數的值在計算機中是以補碼的形式存儲的理論,1000 0001是補碼,即:-127在計算機中是以1000 0001存儲的,-127的原碼是1000 0001補碼)減1,再取反,結果是0111 1111原碼)。
4)-127和-128
這兩個數字都是在范圍之內 沒有什麼可說的了吧,並且它們的二進制形式也剛剛講過了。
5)-129
-129是-128-1所得,所以-128的最後8位是1000 0000,減去1變為0111 1111,前面24位全部置位0,且該數被解釋為正數,其值為2^0+2^1+2^2+2^3+2^4+2^5+2^6=2^7-1=127
6)-130
-127的最後8位是1000 0001,減去3變為0111 1110,前面24位全部保持0,且該數被解釋為正數,其值為2^1+2^2+2^3+2^4+2^5+2^61=126
看了上述的講解 ,我相信讀者一定對unsigned char也明白了,無符號無非就是取值范圍不一樣而已。不過我們還是來一起看一下。總覺得不放心 呵呵
1.程序實例驗證一下unsigned char中溢出的數字的值求unsigned char溢出中的問題)
#include <stdio.h> main() { unsigned char a=254,b=255,c=256,d=257; printf("a=%u\nb=%u\nc=%u\nd=%u\n",a,b,c,d); }
#include <stdio.h> main() { unsigned char a=1,b=0,c=-1,d=-2; printf("a=%u\nb=%u\nc=%u\nd=%u\n",a,b,c,d); }
從上述兩個程序中,我們不難得出以下結論的表格數據。
2.給出unsigned char溢出問題表格的答案:
關於上界溢出
十進制
二進制
值
254
0..0 1111 1110
254
255
0..0 1111 1111
255
256
0..0 0000 0001
0
257
0..0 0000 0001
1
關於下界溢出
十進制
二進制
值
2
0..0 0000 0010
2
1
0..0 0000 0001
1
0
0..0 0000 0000
0
-1
0..0 1111 1111
255
-2
0..0 1111 1110
254
注:0..0 表示24個0,1..1表示24個1
3.解析
其實和有符號基本相同,唯一的差別就是,前面的24位一直都是0,並且該數永遠都是正數。我們說幾個吧。
比如256,256=255+1所得,255為0..0 1111 1111,然後加1,雖然255的全碼都是1,再加1貌似沒法加了,但是我們仍可將1111 1111前面一位加1,最後得到0001 0000 0000,之後我們就只看後8位即可,所以256的值是0.
比如-1,-1=0-1所得,0000 0000減1相當於減去0000 0001,雖然0的全碼是0…0 0000 0000,似乎往上也沒法借位,但是我們仍可將0000 0000前面一位加上1,看做0001 0000 0000減去0000 0000 0001,最後得到0000 1111 1111,我們直接取最後8為即可。
對於無符號型,前24位永遠為0,對於有符號型,前24位永遠和倒數第8位一樣。這個定律可要記清楚了
不知道和大家學習了有無符號char類型以及幾個例子,有沒有對unsigned 和signed了解了很多呢。在上一篇C語言進階暑期特別篇】深入解剖un)signed及溢出上)中的unsigned int和signed int其實和我們這一篇講的是一個道理。
看完C語言進階暑期特別篇】深入解剖un)signed及溢出上)和C語言進階暑期特別篇】深入解剖un)signed及溢出中)兩篇文章後,我和讀者都有一個問題和疑惑,在程序中定義什麼類型就以什麼類型輸出的,如果不是呢?比如:變量a定義為unsigned無符號),但是我們在輸出的時候以signed(有符號)%d)輸出,那又會如何呢?相同的,定義為signed,但是以unsigned輸出,結果又會是如何呢?
這個問題就在下一篇文章C語言進階暑期特別篇】深入解剖un)signed及溢出下)中學習吧。下一篇中我們主要是以一個實際的程序例子來展開陳述,來總結有無符號。
本文出自 “趙玉強的博客” 博客,請務必保留此出處http://zhaoyuqiang.blog.51cto.com/6328846/1259300