Unicode では、すべての文字に U+xxxx という番号(コードポイント)が割り当てられています。 この番号空間は U+0000〜U+10FFFF の約110万通りで構成されており、世界中の文字・記号・絵文字はこの範囲のどこかに配置されています。
UTF‑16 は、この U+ の番号を 16bit(2byte)単位で符号化する方式です。 しかし U+ の番号空間には、2byte(0〜65535)では収まらない領域が存在します。 具体的には U+10000 以上の文字です。
そこで UTF‑16 は、2byte で収まらない文字を扱うために サロゲートペア(2byte × 2 = 4byte) という仕組みを使います。
ところが、このサロゲートペアの仕組みは一見すると分かりづらく、特に次のような疑問が浮かびます。
- 解読側はどうやってサロゲートを見分けるのか
- U+D800〜DFFF の「文字」はどうやって表現するのか
- なぜ Unicode は U+10FFFF で止まっているのか
これらを順番に解きほぐすと、UTF‑16 と Unicode の設計思想が驚くほどクリアになります。
どうやって4byte文字を見分けるのか
UTF‑16 は UTF‑8 のように「先頭ビットのパターン」で文字の長さを判定しません。 代わりに、受け取った 2byte の値そのものを見て判断します。
D800〜DBFF → 上位サロゲート
DC00〜DFFF → 下位サロゲート
デコード側の動作は次のとおりです。
- 最初の 2byte を読む
- その値が D800〜DBFF なら「上位サロゲート」
- 次の 2byte を読む
- その値が DC00〜DFFF なら「下位サロゲート」
- 2つを合成して U+10000 以上の文字を復元する
UTF‑16 は 値の範囲で判定する方式なのです。
上位サロゲート(10bit)と 下位サロゲート(10bit)より、U+0000〜U+10FFFF の範囲を表現します。
U+D800〜DFFF の「文字」はどうやって表現するのか
結論:
U+D800〜DFFF の文字は存在しません。 この範囲は UTF‑16 のサロゲート専用領域であり、 単独で文字として使うことはできません。
- 表現方法は存在しない
- フォントも描画できない
- データに現れたらエラー
- UTF‑16 の内部処理専用の記号である
つまり、「文字として使ってはいけない領域」です。
なぜ Unicode は U+10FFFF で止まっているのか
Unicode の最大値は、まるで「UTF‑16 が先にあったみたいな仕様」になっている理由を考察しました。
Unicode 初期は UCS‑2(UTF‑16 の前身)が主役だった
- 世界中の文字は 65536 あれば足りる
- だから 2byte 固定長で十分
- U+0000〜U+FFFF の範囲だけを使う
しかし文字数が足りなくなったため、拡張が必要になりました。
既存の UCS‑2 を壊さずに拡張するための裏技がサロゲートペア
その結果:
- U+D800〜DFFF を「使えない領域」にする
- そこを使って 4byte の拡張を表現する
- 上位1024 × 下位1024 = 約110万通り
- → U+10000〜U+10FFFF が誕生
まとめ

- U+ は Unicode の文字番号を16進数で表す公式記法
- U+ の番号空間は U+0000〜U+10FFFF(約110万通り)
- UTF‑16 はこの番号空間を 2byte またはサロゲートペア(4byte) で符号化する
- 上位サロゲート:D800〜DBFF(10bit)
- 下位サロゲート:DC00〜DFFF(10bit)
- U+D800〜DFFF は「文字ではない」予約領域
- Unicode の最大値 U+10FFFF は UTF‑16 の都合で決まった
- Unicode 初期は UCS‑2 が主役だったため、UTF‑16 の構造が強く残っている
UTF‑16 のサロゲートペアは「互換性を壊さずに Unicode を拡張するための歴史的な工夫」であり、その背景を理解すると仕様のすべてが腑に落ちます。

HR