サロゲートペア
surrogate pair
https://codezine.jp/article/detail/1592
http://qiita.com/bon127/items/491b25e90208188dafbd#サロゲートペア
わかりやすいmrsekut.icon
gpt-5.icon
1. 背景
Unicode はもともと「16ビット(2バイト)で世界中の文字を表す」という思想で始まりました。
16ビットで表せる範囲は U+0000〜U+FFFF(65,536文字, BMP = Basic Multilingual Plane)。
しかしすぐに「65,536 では足りない!」と判明します。
漢字の拡張
絵文字や記号
古代文字など
そこで Unicode 2.0 以降、21ビット(U+0000〜U+10FFFF) に拡張されました。
2. UTF-16 での問題
UTF-16 は 1 code unit = 16ビット。
つまり 1 code unit では U+0000〜U+FFFF の範囲しか直接表せません。
U+10000 以上の文字を表すために考え出された仕組みが サロゲートペア です。
3. サロゲートペアの仕組み
特殊な領域を利用
Unicode の範囲 U+D800〜U+DFFF(約2,048個) を「通常の文字には使わない特殊領域」として予約。
ここを「上位サロゲート(high surrogate)」と「下位サロゲート(low surrogate)」に分け、組み合わせて1文字を表現する。
ルール
High Surrogate: U+D800〜U+DBFF
Low Surrogate: U+DC00〜U+DFFF
1文字 = high surrogate + low surrogate の2つの code unit
例: 😀 (U+1F600)
1. まず code point から 0x10000 を引く:
0x1F600 - 0x10000 = 0xF600
2. 20ビットの値に分解:
上位10ビット: 0x3D → high
下位10ビット: 0x600 → low
3. サロゲート範囲に加算:
High surrogate = 0xD800 + 0x3D = 0xD83D
Low surrogate = 0xDC00 + 0x600 = 0xDE00
4. UTF-16 の表現 = D83D DE00
4. プログラミングでの落とし穴
JavaScript の String.length は UTF-16 の code unit 数を返す。
code:js
"😀".length // → 2 (サロゲートペアだから2 code units)
サロゲートペアを「文字1つ」として扱いたい場合は、Array.from() や正規表現の u フラグを使う必要がある。
code:js
..."😀".length // → 1
"😀".match(/./u).length // → 1
Python3 などは内部で code point 単位なので len("😀") → 1 となる(実装依存はあるけど論理的には code point ベース)。