編程中,咱們經常使用的仍是10進制……必竟C/C++是高級語言。程序員
好比:編程
int a = 100,b = 99;學習
不過,因爲數據在計算機中的表示,最終以二進制的形式存在,因此有時候使用二進制,能夠更直觀地解決問題。ui
但,二進制數太長了。好比int 類型佔用4個字節,32位。好比100,用int類型的二進制數表達將是:spa
0000 0000 0000 0000 0110 0100操作系統
面對這麼長的數進行思考或操做,沒有人會喜歡。所以,C,C++ 沒有提供在代碼直接寫二進制數的方法。調試
用16進制或8進制能夠解決這個問題。由於,進制越大,數的表達長度也就越短。不過,爲何恰恰是16或8進制,而不其它的,諸如9或20進制呢?htm
二、八、16,分別是2的1次方,3次方,4次方。這一點使得三種進制之間能夠很是直接地互相轉換。8進制或16進制縮短了二進制數,但保持了二進制數的表達特色。在下面的關於進制轉換的課程中,你能夠發現這一點。內存
二進制數第0位的權值是2的0次方,第1位的權值是2的1次方……ci
因此,設有一個二進制數:0110 0100,轉換爲10進製爲:
下面是豎式:
0110 0100 換算成 十進制
第0位 0 * 20 = 0
第1位 0 * 21 = 0
第2位 1 * 22 = 4
第3位 0 * 23 = 0
第4位 0 * 24 = 0
第5位 1 * 25 = 32
第6位 1 * 26 = 64
第7位 0 * 27 = 0 +
---------------------------
100
用橫式計算爲:
0 * 20 + 0 * 21 + 1 * 22 + 1 * 23 + 0 * 24 + 1 * 25 + 1 * 26 + 0 * 27 = 100
0乘以多少都是0,因此咱們也能夠直接跳過值爲0的位:
1 * 22 + 1 * 23 + 1 * 25 + 1 * 26 = 100
八進制就是逢8進1。
八進制數採用 0~7這八數來表達一個數。
八進制數第0位的權值爲8的0次方,第1位權值爲8的1次方,第2位權值爲8的2次方……
因此,設有一個八進制數:1507,轉換爲十進制爲:
用豎式表示:
1507換算成十進制。
第0位 7 * 80 = 7
第1位 0 * 81 = 0
第2位 5 * 82 = 320
第3位 1 * 83 = 512 +
--------------------------
839
一樣,咱們也能夠用橫式直接計算:
7 * 80 + 0 * 81 + 5 * 82 + 1 * 83 = 839
結果是,八進制數 1507 轉換成十進制數爲 839
C,C++語言中,如何表達一個八進制數呢?若是這個數是 876,咱們能夠判定它不是八進制數,由於八進制數中不可能出7以上的阿拉伯數字。但若是這個數是12三、是567,或12345670,那麼它是八進制數仍是10進制數,都有可能。
因此,C,C++規定,一個數若是要指明它採用八進制,必須在它前面加上一個0,如:123是十進制,但0123則表示採用八進制。這就是八進制數在C、C++中的表達方法。
因爲C和C++都沒有提供二進制數的表達方法,因此,這裏所學的八進制是咱們學習的,CtC++語言的數值表達的第二種進製法。
如今,對於一樣一個數,好比是100,咱們在代碼中能夠用日常的10進製表達,例如在變量初始化時:
int a = 100;
咱們也能夠這樣寫:
int a = 0144; //0144是八進制的100;一個10進制數如何轉成8進制,咱們後面會學到。
千萬記住,用八進制表達時,你不能少了最前的那個0。不然計算機會統統當成10進制。不過,有一個地方使用八進制數時,卻不能使用加0,那就是咱們前面學的用於表達字符的「轉義符」表達法。
咱們學過用一個轉義符'\'加上一個特殊字母來表示某個字符的方法,如:'\n'表示換行(line),而'\t'表示Tab字符,'\''則表示單引號。今天咱們又學習了一種使用轉義符的方法:轉義符'\'後面接一個八進制數,用於表示ASCII碼等於該值的字符。
好比,查一下第5章中的ASCII碼錶,咱們找到問號字符(?)的ASCII值是63,那麼咱們能夠把它轉換爲八進值:77,而後用 '\77'來表示'?'。因爲是八進制,因此本應寫成 '\077',但由於C,C++規定不容許使用斜槓加10進制數來表示字符,因此這裏的0能夠不寫。
事實上咱們不多在實際編程中非要用轉義符加八進制數來表示一個字符,因此,6.2.4小節的內容,你們僅僅瞭解就行。
2進制,用兩個阿拉伯數字:0、1;
8進制,用八個阿拉伯數字:0、一、二、三、四、五、六、7;
10進制,用十個阿拉伯數字:0到9;
16進制,用十六個阿拉伯數字……等等,阿拉伯人或說是印度人,只發明瞭10個數字啊?
16進制就是逢16進1,但咱們只有0~9這十個數字,因此咱們用A,B,C,D,E,F這五個字母來分別表示10,11,12,13,14,15。字母不區分大小寫。
十六進制數的第0位的權值爲16的0次方,第1位的權值爲16的1次方,第2位的權值爲16的2次方……
因此,在第N(N從0開始)位上,若是是是數 X (X 大於等於0,而且X小於等於 15,即:F)表示的大小爲 X * 16的N次方。
假設有一個十六進數 2AF5, 那麼如何換算成10進制呢?
用豎式計算:
2AF5換算成10進制:
第0位: 5 * 160 = 5
第1位: F * 161 = 240
第2位: A * 162 = 2560
第3位: 2 * 163 = 8192 +
-------------------------------------
10997
直接計算就是:
5 * 160 + F * 161 + A * 162 +2 * 163 = 10997
(別忘了,在上面的計算中,A表示10,而F表示15)
如今能夠看出,全部進制換算成10進制,關鍵在於各自的權值不一樣。
假設有人問你,十進數 1234 爲何是 一千二百三十四?你盡能夠給他這麼一個算式:
1234 = 1 * 103 + 2 * 102 + 3 * 101 + 4 * 100
若是不使用特殊的書寫形式,16進制數也會和10進制相混。隨便一個數:9876,就看不出它是16進制或10進制。
C,C++規定,16進制數必須以 0x開頭。好比 0x1表示一個16進制數。而1則表示一個十進制。另外如:0xff,0xFF,0X102A,等等。其中的x也也不區分大小寫。(注意:0x中的0是數字0,而不是字母O)
如下是一些用法示例:
int a = 0x100F;
int b = 0x70 + a;
至此,咱們學完了全部進制:10進制,8進制,16進制數的表達方式。最後一點很重要,C/C++中,10進制數有正負之分,好比12表示正12,而-12表示負12,;但8進制和16進制只能用達無符號的正整數,若是你在代碼中裏:-078,或者寫:-0xF2,C,C++並不把它當成一個負數。
轉義符也能夠接一個16進制數來表示一個字符。如在6.2.4小節中說的 '?' 字符,能夠有如下表達方式:
'?' //直接輸入字符
'\77' //用八進制,此時能夠省略開頭的0
'\0x3F' //用十六進制
一樣,這一小節只用於瞭解。除了空字符用八進制數 '\0' 表示之外,咱們不多用後兩種方法表示一個字符。
給你一個十進制,好比:6,若是將它轉換成二進制數呢?
10進制數轉換成二進制數,這是一個連續除2的過程:
把要轉換的數,除以2,獲得商和餘數,
將商繼續除以2,直到商爲0。最後將全部餘數倒序排列,獲得數就是轉換結果。
聽起來有些糊塗?咱們結合例子來講明。好比要轉換6爲二進制數。
「把要轉換的數,除以2,獲得商和餘數」。
那麼:
要轉換的數是6, 6 ÷ 2,獲得商是3,餘數是0。 (不要告訴我你不會計算6÷3!)
「將商繼續除以2,直到商爲0……」
如今商是3,還不是0,因此繼續除以2。
那就: 3 ÷ 2, 獲得商是1,餘數是1。
「將商繼續除以2,直到商爲0……」
如今商是1,還不是0,因此繼續除以2。
那就: 1 ÷ 2, 獲得商是0,餘數是1 (拿筆紙算一下,1÷2是否是商0餘1!)
「將商繼續除以2,直到商爲0……最後將全部餘數倒序排列」
好極!如今商已是0。
咱們三次計算依次獲得餘數分別是:0、一、1,將全部餘數倒序排列,那就是:110了!
6轉換成二進制,結果是110。
把上面的一段改爲用表格來表示,則爲:
被除數 | 計算過程 | 商 | 餘數 |
6 | 6/2 | 3 | 0 |
3 | 3/2 | 1 | 1 |
1 | 1/2 | 0 | 1 |
(在計算機中,÷用 / 來表示)
若是是在考試時,咱們要畫這樣表仍是有點費時間,所更常見的換算過程是使用下圖的連除:
(圖:1)
請你們對照圖,表,及文字說明,而且自已拿筆計算一遍如何將6轉換爲二進制數。
說了半天,咱們的轉換結果對嗎?二進制數110是6嗎?你已經學會如何將二進制數轉換成10進制數了,因此請如今就計算一下110換成10進制是否就是6。
很是開心,10進制數轉換成8進制的方法,和轉換爲2進制的方法相似,唯一變化:除數由2變成8。
來看一個例子,如何將十進制數120轉換成八進制數。
用表格表示:
被除數 | 計算過程 | 商 | 餘數 |
120 | 120/8 | 15 | 0 |
15 | 15/8 | 1 | 7 |
1 | 1/8 | 0 | 1 |
120轉換爲8進制,結果爲:170。
很是很是開心,10進制數轉換成16進制的方法,和轉換爲2進制的方法相似,唯一變化:除數由2變成16。
一樣是120,轉換成16進制則爲:
被除數 | 計算過程 | 商 | 餘數 |
120 | 120/16 | 7 | 8 |
7 | 7/16 | 0 | 7 |
120轉換爲16進制,結果爲:78。
請拿筆紙,採用(圖:1)的形式,演算上面兩個表的過程。
二進制和十六進制的互相轉換比較重要。不過這兩者的轉換卻不用計算,每一個C,C++程序員都能作到看見二進制數,直接就能轉換爲十六進制數,反之亦然。
咱們也同樣,只要學完這一小節,就能作到。
首先咱們來看一個二進制數:1111,它是多少呢?
你可能還要這樣計算:1 * 20 + 1 * 21 + 1 * 22 + 1 * 23 = 1 * 1 + 1 * 2 + 1 * 4 + 1 * 8 = 15。
然而,因爲1111才4位,因此咱們必須直接記住它每一位的權值,而且是從高位往低位記,:八、四、二、1。即,最高位的權值爲23 = 8,而後依次是 22 = 4,21=2, 20 = 1。
記住8421,對於任意一個4位的二進制數,咱們均可以很快算出它對應的10進制值。
下面列出四位二進制數 xxxx 全部可能的值(中間略過部分)
僅4位的2進制數 快速計算方法 十進制值 十六進值
1111 = 8 + 4 + 2 + 1 = 15 F
1110 = 8 + 4 + 2 + 0 = 14 E
1101 = 8 + 4 + 0 + 1 = 13 D
1100 = 8 + 4 + 0 + 0 = 12 C
1011 = 8 + 4 + 0 + 1 = 11 B
1010 = 8 + 0 + 2 + 0 = 10 A
1001 = 8 + 0 + 0 + 1 = 10 9
....
0001 = 0 + 0 + 0 + 1 = 1 1
0000 = 0 + 0 + 0 + 0 = 0 0
二進制數要轉換爲十六進制,就是以4位一段,分別轉換爲十六進制。
如(上行爲二制數,下面爲對應的十六進制):
1111 1101 , 1010 0101 , 1001 1011
F D , A 5 , 9 B
反過來,當咱們看到 FD時,如何迅速將它轉換爲二進制數呢?
先轉換F:
看到F,咱們需知道它是15(可能你還不熟悉A~F這五個數),而後15如何用8421湊呢?應該是8 + 4 + 2 + 1,因此四位全爲1 :1111。
接着轉換 D:
看到D,知道它是13,13如何用8421湊呢?應該是:8 + 2 + 1,即:1011。
因此,FD轉換爲二進制數,爲: 1111 1011
因爲十六進制轉換成二進制至關直接,因此,咱們須要將一個十進制數轉換成2進制數時,也能夠先轉換成16進制,而後再轉換成2進制。
好比,十進制數 1234轉換成二制數,若是要一直除以2,直接獲得2進制數,須要計算較屢次數。因此咱們能夠先除以16,獲得16進制數:
被除數 | 計算過程 | 商 | 餘數 |
1234 | 1234/16 | 77 | 2 |
77 | 77/16 | 4 | 13 (D) |
4 | 4/16 | 0 | 4 |
結果16進製爲: 0x4D2
而後咱們可直接寫出0x4D2的二進制形式: 0100 1011 0010。
其中對映關係爲:
0100 -- 4
1011 -- D
0010 -- 2
一樣,若是一個二進制數很長,咱們須要將它轉換成10進制數時,除了前面學過的方法是,咱們還能夠先將這個二進制轉換成16進制,而後再轉換爲10進制。
下面舉例一個int類型的二進制數:
01101101 11100101 10101111 00011011
咱們按四位一組轉換爲16進制: 6D E5 AF 1B
結束了各類進制的轉換,咱們來談談另外一個話題:原碼、反碼、補碼。
咱們已經知道計算機中,全部數據最終都是使用二進制數表達。
咱們也已經學會如何將一個10進制數如何轉換爲二進制數。
不過,咱們仍然沒有學習一個負數如何用二進制表達。
好比,假設有一 int 類型的數,值爲5,那麼,咱們知道它在計算機中表示爲:
00000000 00000000 00000000 00000101
5轉換成二制是101,不過int類型的數佔用4字節(32位),因此前面填了一堆0。
如今想知道,-5在計算機中如何表示?
在計算機中,負數以其正值的補碼形式表達。
什麼叫補碼呢?這得從原碼,反碼提及。
原碼:一個整數,按照絕對值大小轉換成的二進制數,稱爲原碼。
好比 00000000 00000000 00000000 00000101 是 5的 原碼。
反碼:將二進制數按位取反,所得的新二進制數稱爲原二進制數的反碼。
取反操做指:原爲1,得0;原爲0,得1。(1變0; 0變1)
好比:將00000000 00000000 00000000 00000101每一位取反,得11111111 11111111 11111111 11111010。
稱:11111111 11111111 11111111 11111010 是 00000000 00000000 00000000 00000101 的反碼。
反碼是相互的,因此也可稱:
11111111 11111111 11111111 11111010 和 00000000 00000000 00000000 00000101 互爲反碼。
補碼:反碼加1稱爲補碼。
也就是說,要獲得一個數的補碼,先獲得反碼,而後將反碼加上1,所得數稱爲補碼。
好比:00000000 00000000 00000000 00000101 的反碼是:11111111 11111111 11111111 11111010。
那麼,補碼爲:
11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011
因此,-5 在計算機中表達爲:11111111 11111111 11111111 11111011。轉換爲十六進制:0xFFFFFFFB。
再舉一例,咱們來看整數-1在計算機中如何表示。
假設這也是一個int類型,那麼:
一、先取1的原碼:00000000 00000000 00000000 00000001
二、得反碼: 11111111 11111111 11111111 11111110
三、得補碼: 11111111 11111111 11111111 11111111
可見,-1在計算機裏用二進制表達就是全1。16進製爲:0xFFFFFF。
一切都是紙上說的……說-1在計算機裏表達爲0xFFFFFF,我能不能親眼看一看呢?固然能夠。利用C++ Builder的調試功能,咱們能夠看到每一個變量的16進制值。
下面咱們來動手完成一個小小的實驗,經過調試,觀察變量的值。
咱們在代碼中聲明兩個int 變量,並分別初始化爲5和-5。而後咱們經過CB提供的調試手段,能夠查看到程序運行時,這兩個變量的十進制值和十六進制值。
首先新建一個控制檯工程。加入如下黑體部分(就一行):
//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
int aaaa = 5, bbbbb = -5;
return 0;
}
//---------------------------------------------------------------------------
沒有咱們熟悉的的那一行:
getchar();
因此,若是全速運行這個程序,將只是DOS窗口一閃而過。不過今天咱們將經過設置斷點,來使用程序在咱們須要的地兒停下來。
設置斷點:最經常使用的調試方法之一,使用程序在運行時,暫停在某一代碼位置,
在CB裏,設置斷點的方法是在某一行代碼上按F5或在行首欄內單擊鼠標。
以下圖:
在上圖中,咱們在return 0;這一行上設置斷點。斷點所在行將被CB以紅色顯示。
接着,運行程序(F9),程序將在斷點處停下來。
(請注意兩張圖的不一樣,前面的圖是運行以前,後面這張是運行中,左邊的箭頭表示運行運行到哪一行)
當程序停在斷點的時,咱們能夠觀察當前代碼片斷內,可見的變量。觀察變量的方法不少種,這裏咱們學習使用Debug Inspector (調試期檢視),來全面觀察一個變量。
如下是調出觀察某一變量的 Debug Inspector 窗口的方法:
先確保代碼窗口是活動窗口。(用鼠標點一下代碼窗口)
按下Ctrl鍵,而後將鼠標挪到變量 aaaa 上面,你會發現代碼中的aaaa變藍,而且出現下劃線,效果如網頁中的超連接,而鼠標也變成了小手狀:
點擊鼠標,將出現變量aaaa的檢視窗口:
(筆者使用的操做系統爲WindowsXP,窗口的外觀與Win9X有所不一樣)
從該窗口,我能夠看到:
aaaa :變量名
int :變量的數據類型
0012FF88:變量的內存地址,請參看5.2 變量與內存地址;地址老是使用十六進制表達
5 : 這是變量的值,即aaaa = 5;
0x00000005 :一樣是變量的值,但採用16進製表示。由於是int類型,因此佔用4字節。
首先先關閉前面的用於觀察變量aaaa的Debug Inspector窗口。
如今,咱們用一樣的方法來觀察變量bbbb,它的值爲-5,負數在計算機中使用補碼錶示。
正如咱們所想,-5的補碼爲:0xFFFFFFFB。
再按一次F9,程序將從斷點繼續運行,而後結束。
很難學的一章?
來看看咱們主要學了什麼:
1)咱們學會了如何將2、8、十六進制數轉換爲十進制數。
三種轉換方法是同樣的,都是使用乘法。
2)咱們學會了如何將十進制數轉換爲2、8、十六進制數。
方法也都同樣,採用除法。
3)咱們學會了如何快速的地互換二進制數和十六進制數。
要訣就在於對二進制數按四位一組地轉換成十六進制數。
在學習十六進制數後,咱們會在不少地方採用十六進制數來替代二進制數。
4)咱們學習了原碼、反碼、補碼。
把原碼的0變1,1變0,就獲得反碼。要獲得補碼,則先得反碼,而後加1。
之前咱們只知道正整數在計算機裏是如何表達,如今咱們還知道負數在計算機裏使用其絕對值的補碼錶達。
好比,-5在計算機中如何表達?回答是:5的補碼。
5)最後咱們在上機實驗中,這會了如何設置斷點,如何調出Debug Inspector窗口觀察變量。
之後咱們會學到更多的調試方法。