C語言中char的範圍與原碼補碼反碼

2021-09-24 22:43:42 字數 3613 閱讀 2280

在c語言中,char型別表示有符號整數(signed char)的範圍是-128~+127,而表示無符號整數(unsigned char)的範圍是 0 ~ 255,那麼這幾個數字是怎樣得到的呢

無符號整數

c語言中char型別佔1個位元組,1個位元組就是8個位元位(二進位制位,1 / 0),也就是說,在無符號的情況下,8個位元位所能表示的所有數值就是char的範圍

而在二進位制的八位數中,最小的是0000 0000,也就是十進位制中的0,

最大的是1111 1111,也就是十進位制中的255

所以,unsigned char所能表示的整數值的範圍就是0~255

有符號整數

在原碼中,用最高位表示符號位,'0』表示正號,'1』表示負號,再用剩下的位表示數值,也就是說,無符號時1個位元組8個位元位能表示2^8=256個數(分別是0~255),但是加上了符號後,乙個位元組中真正用來表示數值的位元位只剩下7位,

其中最小的是 000 0000,也就是十進位制中的0,

其中最大的是 111 1111,也就是十進位制中的127

由此算來,表示數值的七位再加上表示符號的最高位,8個位元位能表示的有符號整數的範圍應該是-127~+127,也就是說char型別表示有符號整數的範圍應該是-127~+127,同理,short、int這些型別也應該如此,但教科書上為什麼說是-128~+127呢?事實上為了解決這個問題,還應該了解計算機內部整數儲存形式

原碼為了簡化計算機中的運算器的線路設計,人們設計了一種方法使減法運算轉換成加法運算,即減乙個數等價於加這個數的相反數,這也就引入了原碼、反碼、補碼這三種表示法

原碼是最簡單的機器數表示法,用最高位表示符號位,'0』表示正號,'1』表示負號,其它位存放該數的二進位制的絕對值

下表給出部分正負數的四位二進位制原碼表示法

十進位制二進位制

+00000

-01000

10001

-11001

20010

-21010

可以發現原碼中的0有兩種表示形式,分別是+0和-0

當使用原碼進行計算時:

0001

+0010

=0011

//十進位制:1+2=3 正確

1001

+1010

=10011

//十進位制:(-1)+(-2)=-3 正確

0000

+1000

=1000

//十進位制:(+0)+(-0)=-0 有點問題

0001

+1010

=1011

//十進位制:1+(-2)=(-3) 出錯

0001

+1001

=1010

//十進位制:1+(-1)=-2 出錯

於是發現使用原碼計算加法時除非(+0)+(-0),否則不會出錯,而使用原碼計算減法(即加乙個數的相反數)時,就會發生錯誤,為了解決原碼計算減法出錯的問題,引入了反碼

反碼正數的反碼還是等於原碼,負數的反碼就是它的原碼除符號位外,其餘位按位取反(再加上正數和負數本身符號位就相反,在反碼中,乙個數的正數和負數剛好各位取反)

下表給出部分正負數的四位二進位制反碼表示法

十進位制二進位制

+00000

-01111

10001

-11110

20010

-21101

當使用反碼進行計算時:

0001

+0010

=0011

//十進位制:1+2=3 正確

1110

+1101

=1011

//十進位制:(-1)+(-2)=-4 出錯

0000

+1111

=1111

//十進位制:(+0)+(-0)=-0 有點問題

0001

+1101

=1110

//十進位制:1+(-2)=-1 正確

0001

+1110

=1111

//十進位制:1+(-1)=-0 有點問題

可以發現,解決了減法(也就是正數加乙個負數)的問題,但是在乙個數與其自身的相反數相加時所得的結果不是0而是-0

可是使用反碼進行計算又引入了乙個新的問題,就是在計算兩個負數相加時得到的結果是錯誤的,為了解決這些問題,引入了補碼

補碼正數的補碼等於它的原碼,負數的補碼等於它的反碼+1,這是補碼的第一種演算法,第二種演算法是:負數的補碼等於它的原碼自低位向高位位數的第乙個』1』及其右邊的』0』保持不變,左邊的各位按位取反,符號位不變

下表給出部分正負數的四位二進位制補碼表示法

十進位制二進位制

00000

10001

-11111

20010

-21110

對-0來說,-0的原碼是1000,反碼是1111,補碼是10000,由於溢位了一位將其捨去則得到0000,與+0結果相同

當使用補碼進行計算時:

0001

+0010

=0011

//十進位制:1+2=3 正確

1111

+1110

=1101

//十進位制:(-1)+(-2)=(-3) 正確

0001

+1110

=1111

//十進位制:1+(-2)=-1 正確

0001

+1111

=0000

//十進位制:1+(-1)=0 正確

所以說使用補碼的表示方法就能完美的使用加法運算來計算正數、負數的加減法

並且,在補碼中-0與+0相同,都是0000,於是也就不需要-0這個數了,統一用0000來表示十進位制中的0

有符號整數

現在回過頭來再看char型別,當無符號時,8個位元位能表示2^8=256個數,而0~255恰好是256個數,當有符號時,使用最高位表示符號,還剩7個位元位,但同樣也能表示2*2^7=256個數,之前所說的-127~+127之中只有255個數,少了的乙個其實就是-0,由於補碼中-0與+0相同,所以只需要乙個0(原碼表示為0000 0000)即可,但之前用來表示-0的1000 0000(原碼)就空下來了,於是人們用它來表示-128.

為什麼1000 0000可以表示-128

如果不考慮最高位是8位的話,-128的原碼為1 1000 0000,它的反碼是1 0111 1111,補碼是1 1000 0000,可以看出-128的原碼和補碼相同。同時也可以看出,當我們採取8位計算時,把-128原碼中最高位的1捨去,恰好就是1000 0000,這與-0的原碼相同。並且,在計算中:

0111

1111

+1000

0000

=1111

1111

//十進位制:127+(-128)=-1 正確

有關於-128的計算在-128使用1000 0000這個原碼(補碼)時也是正確的,所以可以用1000 0000表示-128

總結由此,用來表示signed char的8個位元位剛好也就表示了(-127~+127)+128這些剛好256個數。同樣的,signed short、signed int等型別的取值範圍也都是負數比正數多乙個,原因都與signed char相同,它們之中-32768、-2147483647的意義也同樣與-128相同

C語言中char 和 char 的區別

在實習過程中發現了乙個以前一直預設的錯誤,同樣char c abc 和char c abc 前者改變其內容程式是會崩潰的,而後者完全正確。程式演示 首先要搞清楚編譯程式占用的記憶體的分割槽形式 乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放,存放函式...

C語言中char 和 char 區別

原文 c語言中char 和 char 區別 想要把丟掉的東西撿起來,還是很辛苦啊,今天我就發現,我連char 和 char 的區別都不知道。很多人覺得這兩個定義效果一樣,其實差別很大。以下是個人的一些看法,有不正確的地方望指正。本質上來說,char s定義了乙個char型的指標,它只知道所指向的記憶...

C語言 char型別變數範圍

c語言中字元型別也是屬於整型,是否可以用signed和unsigned修飾符?若初系統只提供了127個字元,那麼就將char型別變數的第乙個二進位制位設定為0,用後面7位存放0 127,此時,系統提供的char型別相當於signed char 但實際應用中可用的字元往往會多於127個,據此有的系統提...