小村軟體有限公司
第 2 章

從 ASCII 到 Unicode — 為字元編上號碼

回顧為字元編上號碼的第 1 階段的歷史。從 ASCII 的 128 個字元、日文字元集的百家爭鳴,到為世界上所有字元編上唯一號碼 U+XXXX 的 Unicode。

所有字元編碼的祖先 — ASCII 的 128 個字元

「為字元編上號碼」這個構想的原點,是 1960 年代誕生於美國的 ASCII(American Standard Code for Information Interchange)。ASCII 把英文大寫、英文小寫、數字、符號,以及換行等控制字元,分配到 7 個位元、也就是 0〜127 這 128 個號碼上。

「A」 = 0x41(65)
大寫字母從 0x41 起依序排列。B = 0x42、C = 0x43 …
「a」 = 0x61(97)
小寫字母正好在大寫字母後面 0x20(32)的位置。只差 1 個位元就能做大小寫轉換的設計
「0」 = 0x30(48)
字元「0」與數值 0 是兩回事。這個區別也是理解字元編碼的第一步

如果只有英語圈,這樣就夠了。但世界上的字元數量,遠遠不是 128 個裝得下的。從這裡開始,圍繞「號碼編法」的漫長混亂就此展開。

小題 2-1 — 用數字讀 ASCII

實際用數字讀一讀作為所有字元編碼基石的 ASCII。

Q1. 關於 ASCII 的說明,正確的是哪一個?

Q2. 在 ASCII 中「A」的號碼是十六進位的 0x41。換算成十進位是多少?(十六進位第 2 位數的權重是 16:0x41 = 4 × 16 + 1)

Q3. ASCII 裡連一個日文字元都沒有。之後的發展,正確的是哪一個?

日文的百家爭鳴時代 — 同一份文件在位元組層面卻是兩回事

在日本,包含漢字的字元集(哪個漢字編上幾號)以 JIS 規格的形式被制定出來。然而,把那些號碼變成位元組序列的方式(編碼)卻出現了好幾種。個人電腦的世界是 Shift_JIS,UNIX 的世界是 EUC-JP,電子郵件則是 JIS 編碼(ISO-2022-JP)—— 每個環境各自流行不同的方式。

同樣一句日文的「こんにちは」,Shift_JIS 的檔案與 EUC-JP 的檔案,位元組序列完全是兩回事。請回想第 1 章的口訣 — 收到沒有標籤的位元組序列的一方,只能猜測讀法,猜錯就亂掉。編碼百家爭鳴時代的日文,是亂碼的常客。這個時代的主角 Shift_JIS 至今仍在服役,所以第 4 章會深入到它的結構。

Unicode — 為世界上所有字元,編上唯一的號碼

既然號碼表因語言、因環境而百家爭鳴,那乾脆把世界上所有字元收進一張表,一次編上唯一的號碼 — 這就是 Unicode 的構想。平假名、漢字、阿拉伯文字、表情符號,全都放在同一個號碼空間裡。這個號碼稱為碼位(code point),寫作 U+XXXX(XXXX 是十六進位數)。

「A」 = U+0041
ASCII 的號碼原封不動地嵌在 Unicode 的開頭(為相容性埋下的伏筆)
「あ」 = U+3042
十六進位的 3042 = 十進位的 12354。日文平假名從 U+3041 起排列
「😀」 = U+1F600
表情符號也有號碼。超過 4 位數的大號碼會在第 5 章發揮作用

U+ 後面的十六進位數,習慣之後就能當成普通的數字來讀。十六進位 1 位數是 0〜15,各位數的權重是 1、16、256、4096。0x3042 = 3 × 4096 + 4 × 16 + 2 = 12354 — 只有這個換算,請在小題裡親手算一次。

顯示字元「あ」在 Unicode 中成為碼位 U+3042,再由 UTF-8 變成 E3 81 82、由 UTF-16 變成 30 42 的位元組序列的兩階段圖

Unicode 決定的只到第 1 階段(號碼)。同一個 U+3042,會因第 2 階段的編碼而變成不同的位元組序列。「Unicode = UTF-8」並不成立 — 這是這張圖的要點。

Unicode 只管到「號碼」— 變成位元組的工作還留著

這裡正是第 1 章的兩階段觀點發揮作用的地方。Unicode 解決的只有第 1 階段(號碼編法的統一)。把號碼變成位元組序列的第 2 階段,仍然存在多種方式 — UTF-8、UTF-16、UTF-32。它們都是承載同一套 Unicode 號碼的不同編碼。

光說「支援 Unicode」,並無法確定檔案的位元組序列。實務上被問的永遠是「是 UTF-8 還是 UTF-16?帶不帶 BOM?」這個第 2 階段的選擇。下一章我們就來處理它的代表 UTF-8,實際把位元填進去、親手組出來。

小題 2-2 — Unicode 與碼位

確認 Unicode「為世界上所有字元編上唯一號碼」的構想,以及 U+XXXX 表示法的讀法。

Q4. Unicode 的基本構想,正確的是哪一個?

Q5. 日文字元「あ」的碼位是 U+3042。U+ 後面是十六進位表示。0x3042 換算成十進位是多少?(3 × 4096 + 0 × 256 + 4 × 16 + 2)

Q6. 「U+3042」這個表示法指的是哪一個?

本章帶走的重點

  • ASCII 是 7 位元、128 個字元。「A」= 0x41 = 65。是許多字元編碼的基石
  • 日文經歷了 Shift_JIS、EUC-JP 等編碼百家爭鳴的漫長時代,是亂碼的溫床
  • Unicode 為世界上所有字元編上唯一的號碼(碼位,U+XXXX)。「あ」= U+3042 = 12354
  • Unicode 決定的只到號碼為止。變成位元組的第 2 階段(UTF-8 等)仍是另一個選擇

下一章終於輪到第 2 階段的主角 UTF-8。U+3042 變成 E3 81 82 的過程,由你自己親手計算。