一文說清文字編碼那些事
阿新 • • 發佈:2020-03-13
一直以來,編碼問題像幽靈一般,不少開發人員都受過它的困擾。
試想你請求一個數據,卻得到一堆亂碼,丈二和尚摸不著頭腦。有同事質疑你的資料是亂碼,雖然你很確定傳了 *UTF-8* ,卻也無法自證清白,更別說幫同事 *debug* 了。
有時,靠著百度和一手瞎調的手藝,亂碼也能解決。儘管如此,還是很羨慕那些骨灰級程式設計師。為什麼他們每次都能犀利地指出問題,並快速修復呢?原因在於,他們早就把編碼問題背後的各種來龍去脈搞清楚了。
本文從 [ASCII](https://en.wikipedia.org/wiki/ASCII) 碼說起,帶你扒一扒編碼背後那些事。相信搞清編碼的原理後,你將不再畏懼任何編碼問題。
## 從 ASCII 碼說起
現代計算機技術從英文國家興起,最先遇到的也是英文文字。英文文字一般由 *26* 個字母、 *10* 個數字以及若干符號組成,總數也不過 *100* 左右。
計算機中最基本的儲存單位為 **位元組** ( *byte* ),由 *8* 個位元位( *bit* )組成,也叫做 **八位位元組** ( *octet* )。*8* 個位元位可以表示 $ 2^8 = 256 $ 個字元,看上去用位元組來儲存英文字元即可?
計算機先驅們也是這麼想的。他們為每個英文字元編號,再加上一些控制符,形成了我們所熟知的 [ASCII](https://en.wikipedia.org/wiki/ASCII) 碼錶。實際上,由於英文字元不多,他們只用了位元組的後 *7* 位而已。
![](https://python.fasionchan.com/zh_CN/latest/_images/fd3a4b1205b5bb1511ae43303a7275a3.png)
根據 *ASCII* 碼錶,由 *01000001* 這 *8* 個位元位組成的八位位元組,代表字母 *A* 。
![](https://python.fasionchan.com/zh_CN/latest/_images/7f524be0e18ac44cc71276393e60718a.svg)
順便提一下,位元本身沒有意義,**位元** 在 **上下文** ( *context* )中才構成資訊。舉個例子,對於記憶體中一個位元組 *01000001* ,你將它看做一個整數,它就是 *65* ;將它作為一個英文字元,它就是字母 *A* ;你看待位元的方式,就是所謂的上下文。
所以,猜猜下面這個程式輸出啥?
```c
#