程序 = 算法 + 數(shù)據(jù)結(jié)構(gòu)。對(duì)應(yīng)硬件,算法就是計(jì)算機(jī)指令,數(shù)據(jù)結(jié)構(gòu)就對(duì)應(yīng)二進(jìn)制數(shù)據(jù)。
計(jì)算機(jī)都是用 0 和 1 組成的二進(jìn)制,表示所有信息。指令用到的機(jī)器碼也是二進(jìn)制表示;內(nèi)存里字符串、整數(shù)、浮點(diǎn)數(shù)也是。
快速瀏覽一遍整數(shù)、文本字符串的二進(jìn)制表示。遇到亂碼是怎么回事兒、Unicode 和 UTF-8 之間有什么關(guān)系。
一、理解二進(jìn)制的“逢二進(jìn)一”
十進(jìn)制整數(shù),都能通過(guò)二進(jìn)制表示出來(lái)。二進(jìn)制對(duì)應(yīng)到十進(jìn)制,比如 0011?=3

把 13 這個(gè)十進(jìn)制數(shù),用短除法轉(zhuǎn)化成二進(jìn)制,=?1101

負(fù)數(shù):最左側(cè)的一位,當(dāng)成是對(duì)應(yīng)的正負(fù)號(hào),比如 0 為正數(shù),1 為負(fù)數(shù)
0011 = +3。補(bǔ)碼1011 = -3。整數(shù)的原碼表示法。缺點(diǎn)1000 代表 0, 0000 也代表 0。
另一種表示法=-5:

最高位1必然是負(fù),最高位 0必然是正。 0000 表示 0,1000 表示 -8。4 位二進(jìn)制數(shù),可從 -8 到 7 這 16 個(gè)整數(shù),不會(huì)浪費(fèi)一位。
?-5 + 1 = -4,-5 + 6 = 1。

字符串的表示,從編碼到數(shù)字,都可用二進(jìn)制表示。
二、ASCII 碼
8 位二進(jìn)制,表示需要所有字符(American Standard Code for Information Interchange,美國(guó)信息交換標(biāo)準(zhǔn)代碼)。

ASCII 碼就好比字典, 128 個(gè)不同數(shù)(8 位二進(jìn)制)映射到 128 個(gè)不同字符里。a 在 ASCII 里是第 97 個(gè),二進(jìn)制 0110 0001,十六進(jìn)制 61。A第 65 個(gè),二進(jìn)制0100 0001,十六進(jìn)制41。
ASCII ,9 不是 0000 1001,而是 0011 1001。15 不是用 0000 1111,兩個(gè)字符 1 和 5 連續(xù)放在一起,就是 0011 0001 和 0011 0101,用兩個(gè) 8 位表示。
最大的 32 位整數(shù),2147483647。用整數(shù)只需 32 位。用字符串(多占空間)有 10 個(gè)字符,每個(gè)字符用 8 位的話(huà),需要整整 80 位。
存儲(chǔ)數(shù)據(jù)用二進(jìn)制序列化,不是簡(jiǎn)單地把數(shù)據(jù)通過(guò) CSV 或者 JSON進(jìn)行序列化。不管是整數(shù)也好,浮點(diǎn)數(shù)也好,采用二進(jìn)制序列化會(huì)比存儲(chǔ)文本省下不少空間。
ASCII 碼只表示了 128 個(gè)字符不太夠用。于是創(chuàng)建了對(duì)應(yīng)的字符集(Charset)和字符編碼(Character Encoding)。
字符集,字符的集合。比如“中文(《新華字典》里面出現(xiàn)的所有漢字)”就是一個(gè)字符集,“”, Unicode是字符集,150 種語(yǔ)言14 萬(wàn)個(gè)不同的字符。
字符編碼:字符(字符集里)用二進(jìn)制表示的字典。 Unicode可用 UTF-8、UTF-16編碼存儲(chǔ)成二進(jìn)制。有了 Unicode可用不止 UTF-8 一種編碼形式,知道編碼規(guī)則,可以正常傳輸、顯示代碼。

同樣文本不同編碼存儲(chǔ)。另一個(gè)程序,不同的編碼方式來(lái)進(jìn)行解碼和展示,就會(huì)亂碼。就像密語(yǔ)通信,用錯(cuò)密碼本不知所云。

搜索郵件歷史出現(xiàn)了“錕斤拷”
想要 Unicode 編碼記錄文本,但這些字符在 Unicode 中并不存在。Unicode 統(tǒng)一記錄為 U+FFFD 編碼。如果用 UTF-8 的格式存儲(chǔ)下來(lái),就是\xef\xbf\xbd。如果連續(xù)兩個(gè)這樣的字符放在一起,\xef\xbf\xbd\xef\xbf\xbd,這個(gè)時(shí)候,如果程序把這個(gè)字符,用 GB2312 的方式進(jìn)行 decode,就會(huì)變成“錕斤拷”。這就好比我們用 GB2312 這本密碼本,去解密別人用 UTF-8 加密的信息,自然沒(méi)辦法讀出有用的信息。
而“燙燙燙”,則是因?yàn)槿绻阌昧?Visual Studio 的調(diào)試器,默認(rèn)使用 MBCS 字符集。“燙”在里面是由 0xCCCC 來(lái)表示的,而 0xCC 又恰好是未初始化的內(nèi)存的賦值。于是,在讀到沒(méi)有賦值的內(nèi)存地址或者變量時(shí),電腦就開(kāi)始大叫“燙燙燙”了。
課后思考
負(fù)數(shù)是原碼表示,應(yīng)該如何處理?如果是補(bǔ)碼表示的呢?請(qǐng)你用二進(jìn)制加法試著算一算,-5+4=-1,通過(guò)原碼和補(bǔ)碼是如何進(jìn)行的?
[-5+4]補(bǔ)=[-5]補(bǔ)+[4]補(bǔ)=[1011+0100]補(bǔ)=[1111]補(bǔ)? 原碼1001