亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

重學(xué)計(jì)算機(jī)組成原理(十)- "燙燙燙"亂碼的由來(lái)

wenzi / 2861人閱讀

摘要:而大寫(xiě)字母,就是第個(gè),也就是二進(jìn)制的,對(duì)應(yīng)的十六進(jìn)制表示就是。在中文世界里,最典型的就是手持兩把錕斤拷,口中疾呼燙燙燙的典故。既然今天要徹底搞清楚編碼知識(shí),我們就來(lái)弄清楚錕斤拷和燙燙燙的來(lái)龍去脈。參考深入淺出計(jì)算機(jī)組成原理

程序 = 算法 + 數(shù)據(jù)結(jié)構(gòu)

對(duì)應(yīng)到計(jì)算機(jī)的組成原理(硬件層面)

算法 --- 各種計(jì)算機(jī)指令

數(shù)據(jù)結(jié)構(gòu) --- 二進(jìn)制數(shù)據(jù)

計(jì)算機(jī)用0/1組成的二進(jìn)制,來(lái)表示所有信息

程序指令用到的機(jī)器碼,是使用二進(jìn)制表示的

存儲(chǔ)在內(nèi)存里面的字符串、整數(shù)、浮點(diǎn)數(shù)也都是用二進(jìn)制表示的

萬(wàn)物在計(jì)算機(jī)里都是0和1,搞清楚各種數(shù)據(jù)在二進(jìn)制層面是怎么表示的,是我們的必修課。

在實(shí)際應(yīng)用中最常遇到的問(wèn)題,也就是文本字符串是怎么表示成二進(jìn)制的,特別是我們會(huì)遇到的亂碼究竟是怎么回事兒

在開(kāi)發(fā)的時(shí)候,所說(shuō)的Unicode和UTF-8之間有什么關(guān)系。

理解了這些,相信以后遇到任何亂碼問(wèn)題,你都能手到擒來(lái)了。

1 理解二進(jìn)制的“逢二進(jìn)一”

二進(jìn)制和我們平時(shí)用的十進(jìn)制,并沒(méi)有本質(zhì)區(qū)別,只是平時(shí)是“逢十進(jìn)一”,這里變成了“逢二進(jìn)一”

每一位,相比于十進(jìn)制下的0~9這十個(gè)數(shù)字,我們只能用0和1這兩個(gè)數(shù)字。

任何一個(gè)十進(jìn)制的整數(shù),都能通過(guò)二進(jìn)制表示出來(lái)

把一個(gè)二進(jìn)制數(shù),對(duì)應(yīng)到十進(jìn)制,非常簡(jiǎn)單,就是把從右到左的第N位,乘上一個(gè)2的N次方,然后加起來(lái),就變成了一個(gè)十進(jìn)制數(shù)

當(dāng)然,既然二進(jìn)制是一個(gè)面向程序員的“語(yǔ)言”,這個(gè)從右到左的位置,自然是從0開(kāi)始的。

比如_0011_這個(gè)二進(jìn)制數(shù),對(duì)應(yīng)的十進(jìn)制表示,就是

$0×2^3+0×2^2+1×2^1+1×2^0$
$=3$

代表十進(jìn)制的3

對(duì)應(yīng)地,如果我們想要把一個(gè)十進(jìn)制的數(shù),轉(zhuǎn)化成二進(jìn)制,使用短除法就可以了

也就是,把十進(jìn)制數(shù)除以2的余數(shù),作為最右邊的一位。然后用商繼續(xù)除以2,把對(duì)應(yīng)的余數(shù)緊靠著剛才余數(shù)的右側(cè),這樣遞歸迭代,直到商為0就可以了。

比如,我們想把13這個(gè)十進(jìn)制數(shù),用短除法轉(zhuǎn)化成二進(jìn)制,需要經(jīng)歷以下幾個(gè)步驟:


因此,對(duì)應(yīng)的二進(jìn)制數(shù),就是1101

剛才我們舉的例子都是正數(shù),對(duì)于負(fù)數(shù)來(lái)說(shuō),情況也是一樣的嗎?

我們可以把一個(gè)數(shù)最左側(cè)的一位,當(dāng)成是對(duì)應(yīng)的正負(fù)號(hào),比如0為正數(shù),1為負(fù)數(shù),這樣來(lái)進(jìn)行標(biāo)記。

這樣,一個(gè)4位的二進(jìn)制數(shù), 0011就表示為+3。而1011最左側(cè)的第一位是1,所以它就表示-3。這個(gè)其實(shí)就是整數(shù)的原碼表示法

原碼表示法有一個(gè)很直觀的缺點(diǎn)就是,0可以用兩個(gè)不同的編碼來(lái)表示,1000代表0, 0000也代表0。習(xí)慣萬(wàn)事一一對(duì)應(yīng)的程序員看到這種情況,必然會(huì)被“逼死”。

于是,我們就有了另一種表示方法。我們?nèi)匀煌ㄟ^(guò)最左側(cè)第一位的0和1,來(lái)判斷這個(gè)數(shù)的正負(fù)。但是,我們不再把這一位當(dāng)成多帶帶的符號(hào)位,在剩下幾位計(jì)算出的十進(jìn)制前加上正負(fù)號(hào),而是在計(jì)算整個(gè)二進(jìn)制值的時(shí)候,在左側(cè)最高位前面加個(gè)負(fù)號(hào)。

比如,一個(gè)4位的二進(jìn)制補(bǔ)碼數(shù)值1011,轉(zhuǎn)換成十進(jìn)制,就是

$-1×2^3+0×2^2+1×2^1+1×2^0$
$=-5$

如果最高位是1,這個(gè)數(shù)必然是負(fù)數(shù);最高位是0,必然是正數(shù)。并且,只有0000表示0,1000在這樣的情況下表示-8。一個(gè)4位的二進(jìn)制數(shù),可以表示從-8到7這16個(gè)整數(shù),不會(huì)白白浪費(fèi)一位。

當(dāng)然更重要的一點(diǎn)是,用補(bǔ)碼來(lái)表示負(fù)數(shù),使得我們的整數(shù)相加變得很容易,不需要做任何特殊處理,只是把它當(dāng)成普通的二進(jìn)制相加,就能得到正確的結(jié)果。

我們簡(jiǎn)單一點(diǎn),拿一個(gè)4位的整數(shù)來(lái)算一下,比如 -5 + 4 = -1,-5 + 6 = 1

我們各自把它們轉(zhuǎn)換成二進(jìn)制來(lái)看一看。如果它們和無(wú)符號(hào)的二進(jìn)制整數(shù)的加法用的是同樣的計(jì)算方式,這也就意味著它們是同樣的電路。

2 字符串的表示,從編碼到數(shù)字

不僅數(shù)值可以用二進(jìn)制表示,字符乃至更多的信息都能用二進(jìn)制表示

最典型的例子就是字符串(Character String)

最早計(jì)算機(jī)只需要使用英文字符,加上數(shù)字和一些特殊符號(hào),然后用8位的二進(jìn)制,就能表示我們?nèi)粘P枰乃凶址?,這個(gè)就是我們常常說(shuō)的ASCII碼(American Standard Code for Information Interchange,美國(guó)信息交換標(biāo)準(zhǔn)代碼)

ASCII碼就好比一個(gè)字典,用8位二進(jìn)制中的128個(gè)不同的數(shù),映射到128個(gè)不同的字符里

比如,小寫(xiě)字母a在ASCII里面,就是第97個(gè),也就是二進(jìn)制的0110 0001,對(duì)應(yīng)的十六進(jìn)制表示就是 61。而大寫(xiě)字母 A,就是第65個(gè),也就是二進(jìn)制的0100 0001,對(duì)應(yīng)的十六進(jìn)制表示就是41。

在ASCII碼里面,數(shù)字9不再像整數(shù)表示法里一樣,用0000 1001來(lái)表示,而是用0011 1001 來(lái)表示。字符串15也不是用0000 1111 這8位來(lái)表示,而是變成兩個(gè)字符1和5連續(xù)放在一起,也就是 0011 0001 和 0011 0101,需要用兩個(gè)8位來(lái)表示。

我們可以看到,最大的32位整數(shù),就是2147483647。如果用整數(shù)表示法,只需要32位就能表示了。但是如果用字符串來(lái)表示,一共有10個(gè)字符,每個(gè)字符用8位的話,需要整整80位。比起整數(shù)表示法,要多占很多空間。

這也是為什么,很多時(shí)候我們?cè)诖鎯?chǔ)數(shù)據(jù)的時(shí)候,要采用二進(jìn)制序列化這樣的方式,而不是簡(jiǎn)單地把數(shù)據(jù)通過(guò)CSV或者JSON,這樣的文本格式存儲(chǔ)來(lái)進(jìn)行序列化。不管是整數(shù)也好,浮點(diǎn)數(shù)也好,采用二進(jìn)制序列化會(huì)比存儲(chǔ)文本省下不少空間。

ASCII碼只表示了128個(gè)字符,一開(kāi)始倒也堪用,畢竟計(jì)算機(jī)是在美國(guó)發(fā)明的

然而隨著越來(lái)越多的不同國(guó)家的人都用上了計(jì)算機(jī),想要表示譬如中文這樣的文字,128個(gè)字符顯然是不太夠用的。于是,計(jì)算機(jī)工程師們開(kāi)始各顯神通,給自己國(guó)家的語(yǔ)言創(chuàng)建了對(duì)應(yīng)的字符集(Charset)和字符編碼(Character Encoding)

字符集

表示的可以是字符的一個(gè)集合

比如“中文”就是一個(gè)字符集,不過(guò)這樣描述一個(gè)字符集并不準(zhǔn)確

想要更精確一點(diǎn),我們可以說(shuō),“第一版《新華字典》里面出現(xiàn)的所有漢字”,這是一個(gè)字符集。這樣,我們才能明確知道,一個(gè)字符在不在這個(gè)集合里面

比如,我們?nèi)粘Uf(shuō)的Unicode,其實(shí)就是一個(gè)字符集,包含了150種語(yǔ)言的14萬(wàn)個(gè)不同的字符。

字符編碼

則是對(duì)于字符集里的這些字符,怎么一一用二進(jìn)制表示出來(lái)的一個(gè)字典

我們上面說(shuō)的Unicode,就可以用UTF-8、UTF-16,乃至UTF-32來(lái)進(jìn)行編碼,存儲(chǔ)成二進(jìn)制。所以,有了Unicode,其實(shí)我們可以用不止UTF-8一種編碼形式,我們也可以自己發(fā)明一套 GT-32 編碼,比如就叫作Geek Time 32好了。只要?jiǎng)e人知道這套編碼規(guī)則,就可以正常傳輸、顯示這段代碼。

同樣的文本,采用不同的編碼存儲(chǔ)下來(lái)。如果另外一個(gè)程序,用一種不同的編碼方式來(lái)進(jìn)行解碼和展示,就會(huì)出現(xiàn)亂碼。這就好像兩個(gè)軍隊(duì)用密語(yǔ)通信,如果用錯(cuò)了密碼本,那看到的消息就會(huì)不知所云。在中文世界里,最典型的就是“手持兩把錕斤拷,口中疾呼燙燙燙”的典故。

沒(méi)有經(jīng)驗(yàn)的同學(xué),在看到程序輸出“燙燙燙”的時(shí)候,以為是程序讓CPU過(guò)熱發(fā)出報(bào)警,于是嘗試給CPU降頻來(lái)解決問(wèn)題。

既然今天要徹底搞清楚編碼知識(shí),我們就來(lái)弄清楚“錕斤拷”和“燙燙燙”的來(lái)龍去脈。

“錕斤拷”的來(lái)源

如果我們想要用Unicode編碼記錄一些文本,特別是一些遺留的老字符集內(nèi)的文本,但是這些字符在Unicode中可能并不存在。于是,Unicode會(huì)統(tǒng)一把這些字符記錄為U+FFFD這個(gè)編碼

如果用UTF-8的格式存儲(chǔ)下來(lái),就是xefxbfxbd。如果連續(xù)兩個(gè)這樣的字符放在一起,xefxbfxbdxefxbfxbd,這個(gè)時(shí)候,如果程序把這個(gè)字符,用GB2312的方式進(jìn)行decode,就會(huì)變成“錕斤拷”。這就好比我們用GB2312這本密碼本,去解密別人用UTF-8加密的信息,自然沒(méi)辦法讀出有用的信息。

而“燙燙燙”,則是因?yàn)槿绻阌昧薞isual Studio的調(diào)試器,默認(rèn)使用MBCS字符集

“燙”在里面是由0xCCCC來(lái)表示的,而0xCC又恰好是未初始化的內(nèi)存的賦值。于是,在讀到?jīng)]有賦值的內(nèi)存地址或者變量的時(shí)候,電腦就開(kāi)始大叫“燙燙燙”了。

3 總結(jié)延伸

到這里,相信你發(fā)現(xiàn),我們可以用二進(jìn)制編碼的方式,表示任意的信息。只要建立起字符集和字符編碼,并且得到大家的認(rèn)同,我們就可以在計(jì)算機(jī)里面表示這樣的信息了。所以說(shuō),如果你有心,要發(fā)明一門(mén)自己的克林貢語(yǔ)并不是什么難事。

不過(guò),光是明白怎么把數(shù)值和字符在邏輯層面用二進(jìn)制表示是不夠的。我們?cè)谟?jì)算機(jī)組成里面,關(guān)心的不只是數(shù)值和字符的邏輯表示,更要弄明白,在硬件層面,這些數(shù)值和我們一直提的晶體管和電路有什么關(guān)系。下一講,我就會(huì)為你揭開(kāi)神秘的面紗。我會(huì)從時(shí)鐘和D觸發(fā)器講起,最終讓你明白,計(jì)算機(jī)里的加法,是如何通過(guò)電路來(lái)實(shí)現(xiàn)的。

4 推薦閱讀

《編碼:隱匿在計(jì)算機(jī)軟硬件背后的語(yǔ)言》


從電報(bào)機(jī)到計(jì)算機(jī),這本書(shū)講述了很多計(jì)算設(shè)備的歷史故事,當(dāng)然,也包含了二進(jìn)制及其背后對(duì)應(yīng)的電路原理。

參考

深入淺出計(jì)算機(jī)組成原理

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/76262.html

相關(guān)文章

  • 理解函數(shù)棧幀

    摘要:同時(shí),和所指示的位置會(huì)隨著函數(shù)棧幀的創(chuàng)建和銷(xiāo)毀而不斷的發(fā)生改變。再次執(zhí)行函數(shù)棧幀的創(chuàng)建操作。函數(shù)的返回值會(huì)存在一個(gè)寄存器中當(dāng)函數(shù)棧幀釋放后,返回值不會(huì)隨之消失。二函數(shù)棧幀的銷(xiāo)毀將一些函數(shù)調(diào)用中使用的寄存器彈出棧。 ...

    番茄西紅柿 評(píng)論0 收藏0
  • 重學(xué)計(jì)算機(jī)組成原理(五)- "旋轉(zhuǎn)跳躍"指令實(shí)現(xiàn)

    摘要:在中央處理器的控制部件中,包含的寄存器有指令寄存器和程序計(jì)數(shù)器。這條指令的第一個(gè)操作數(shù),代表累加寄存器在中央處理器中,累加器是一種寄存器,用來(lái)儲(chǔ)存計(jì)算產(chǎn)生的中間結(jié)果。第二個(gè)操作數(shù)則是進(jìn)制的的表示。 showImg(https://ask.qcloudimg.com/http-save/1752328/57mlmnq3i5.png); CPU執(zhí)行的也不只是一條指令,一般一個(gè)程序包含很多條...

    siberiawolf 評(píng)論0 收藏0
  • 重學(xué)計(jì)算機(jī)組成原理一)- 門(mén)電路"千里傳音"

    摘要:公元前年,在雅典附近的馬拉松海邊,發(fā)生了波斯和希臘之間的希波戰(zhàn)爭(zhēng)。因?yàn)殡妶?bào)員要熟記每一個(gè)字母對(duì)應(yīng)的摩爾斯電碼,并且需要快速按鍵來(lái)進(jìn)行輸入。 showImg(https://image-static.segmentfault.com/548/184/548184927-5d5962191cbce_articlex); 人用紙和筆來(lái)做運(yùn)算,都是用十進(jìn)制,直接用十進(jìn)制和我們最熟悉的符號(hào)不是最...

    Shihira 評(píng)論0 收藏0
  • 重學(xué)計(jì)算機(jī)組成原理(一)- 馮·諾依曼體系結(jié)構(gòu)

    摘要:馮諾依曼體系結(jié)構(gòu)示意圖總結(jié)馮諾依曼體系結(jié)構(gòu)確立了我們現(xiàn)在每天使用的計(jì)算機(jī)硬件的基礎(chǔ)架構(gòu)。因此,學(xué)習(xí)計(jì)算機(jī)組成原理,其實(shí)就是學(xué)習(xí)和拆解馮諾依曼體系結(jié)構(gòu)。 showImg(https://ask.qcloudimg.com/http-save/1752328/g6cdrb45jg.png); 1 計(jì)算機(jī)的基本硬件組成 早期,DIY一臺(tái)計(jì)算機(jī),要先有三大件 CPU 內(nèi)存 主板 1.1 C...

    Yujiaao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<