EmoArt
投稿する
用語集

サロゲートペア (Surrogate Pair) とは

最終更新: 2026-05-19·約 4 分

この記事は約 4 分で読めます。

絵文字を 1 つ入力したのに「2 文字」とカウントされる現象。その正体がサロゲートペアです。Unicode の表現範囲を UTF-16 という古い設計で扱おうとすると、1 文字を表すのに 2 つの「片割れ」を使わざるを得ない場面があります。 この片割れの組のことをサロゲートペアと呼びます。絵文字や一部の漢字を扱うときに必ず登場する基礎概念です。

定義

サロゲートペアとは、UTF-16 において U+FFFF を超える Unicode コードポイントを 2 つの 16 ビット単位で表現する仕組みです。 前半を「上位サロゲート」(High Surrogate, U+D800〜U+DBFF)、後半を「下位サロゲート」(Low Surrogate, U+DC00〜U+DFFF) と呼び、 この 2 つが必ず対 (ペア) で出現します。

なぜ必要なのか

Unicode は U+0000 から U+10FFFF までの広大なコードポイント空間を持っています。これを表現するには 21 ビット必要です。 しかし UTF-16 は 1 単位 16 ビットの設計のため、U+FFFF までしか単独では表現できません。 この限界を超える文字 (絵文字の大半、一部の漢字、古代文字、数学記号など) を扱うために、上位と下位を組み合わせて拡張する仕組みが導入されました。

絵文字との関係

絵文字のコードポイントの多くは U+1F000 以降の領域にあり、UTF-16 ではサロゲートペアで表現されます。 たとえば 🌸 (U+1F338) は、UTF-16 では D83C DF38 という 2 つの 16 ビット単位として格納されます。 この事実が、JavaScript の文字列長カウントで絵文字 1 つが 2 になる現象の直接の原因です。

JavaScript の挙動

JavaScript の String は内部的に UTF-16 で表現されているため、.length はサロゲートペアを 2 とカウントします。

結果意味
"あ".length1BMP 内なのでペア不要
"🌸".length2サロゲートペアで構成
[..."🌸"].length1コードポイント単位の分解
"🌸".codePointAt(0)127800結合されたコードポイント値

UTF-8 / UTF-32 との違い

サロゲートペアは UTF-16 固有の仕組みです。UTF-8 は 1〜4 バイトの可変長で全コードポイントを表現でき、UTF-32 は 4 バイト固定で全コードポイントを 1 単位で扱います。 UTF-8 や UTF-32 を使う言語・処理系では、サロゲートペアの概念は登場しません。

実務での使われ方

  • 文字数バリデーション: フォームの最大文字数を「人間が認識する文字単位」で数えたい場面でサロゲートペアの理解が必要
  • テキスト処理: 部分文字列の切り出し、逆順処理、正規表現マッチで、サロゲートペアを 1 単位として扱う必要がある
  • ファイル名・データベース: 古いシステムがサロゲートペアを正しく扱えず、絵文字を含むデータが破損するケース
  • SNS の文字数カウント: 各プラットフォームのカウントロジックの差は、サロゲートペアと書記素クラスタの扱いの違いから生まれる

正しく数える方法

ユーザーが「1 文字」と認識する単位で数えたいなら、サロゲートペア単位ではなく書記素クラスタ単位で数える必要があります。 モダンな JavaScript では Intl.Segmenter が標準で利用可能で、絵文字や ZWJ シーケンスも適切に 1 単位として扱えます。

よくある誤解

  • ❌ 「絵文字は全部 2 文字扱い」→ ✅ U+FFFF 以下にある絵文字 (一部の古い記号系) はペア不要で 1 文字
  • ❌ 「サロゲートペアは UTF-8 でも使う」→ ✅ UTF-16 固有の仕組み
  • ❌ 「上位サロゲート単独でも文字として有効」→ ✅ 単独では不正な Unicode 文字列 (Unpaired Surrogate)

関連用語

  • Unicode - 文字の国際規格
  • 絵文字 - サロゲートペアで表現されることが多い

この記事は役に立ちましたか?