在不同基底間轉換
一旦你接受 42、0x2A 和 0b101010 是同一個數字穿著不同衣服,實際的問題就是:怎麼用手替它換裝?在不同基底間轉換不過是記帳,而你最常做的三種轉換,稍加練習就能在腦中完成。
二進位轉十六進位(以及反過來)最容易,因為四個位元構成一個十六進位數字:從「右邊」起把位元每四個一組,再翻譯每一組。1101 0011 拆成 1101(即 8+4+1 = 13 = 十六進位 d)和 0011(即 3),所以是 0xd3。反方向則把每個十六進位數字展開成它的四個位元。要把二進位轉成十進位,就把為 1 的位元的位值加起來:0b101010 在 32、8、2 這幾位上是 1,而 32 + 8 + 2 = 42。要把十進位數轉成二進位,最整齊的方法是反覆除以 2:除一次、寫下餘數,然後由下往上讀餘數——42 / 2 = 21 餘 0,21 / 2 = 10 餘 1,10 / 2 = 5 餘 0,5 / 2 = 2 餘 1,2 / 2 = 1 餘 0,1 / 2 = 0 餘 1,由下往上讀就是 101010。
在真實程式裡你幾乎從不手動轉換——printf 的 %x、%o,或自己寫的二進位輸出就能做到,strtol() 能解析任意基底的字串,除錯器也能隨時顯示十六進位。但理解其中的機制能讓你不被唬住:知道 0x100 是 256 而不是 100,或者知道高位十六進位數字承載一個位元組最上面的四個位元,這種流暢度會讓閱讀記憶體傾印和位元遮罩變得自然,而不再神祕。
十進位 42 -> 二進位用反覆除以 2:餘數由下往上是 1,0,1,0,1,0 -> 101010。從右起分組成 10 1010,補滿成 0010 1010,讀成十六進位 0x2A。
十進位轉二進位用反覆除法;二進位與十六進位互轉用每四位分組。
把位元分組成十六進位半位元組時,務必從「右邊」(低位端)開始分組,並在最左邊那組補零;從左邊分組會得到錯誤答案。