最終更新日時(UTC): 2025年07月10日 01時26分30秒
Koichi Murase が更新

履歴 編集

# char16_tとchar32_t [N2249](C++11)

このページはC++11に採用された言語機能の変更を解説しています。

のちのC++規格でさらに変更される場合があるため関連項目を参照してください。

## 概要

`char16_t`はUTF-16符号化形式の文字型、`char32_t`はUTF-32符号化形式の文字型である。

UTF-16とUTF-32は、ISO/IEC 10646で標準化されている文字コード「UCS (Universal Coded Character Set)」とその互換文字コードである「Unicode (ユニコード)」で定義されている符号化形式である。UTF-16は、ひとつのコードポイント(≒文字)を表すために16ビットを基本的に使用する。UTF-32は32ビットである。

標準C++では、これらの文字符号化形式を表す文字型、そのリテラル、および文字コード・符号化形式を変換する機能を提供する。

    // UTF-16／UTF-32符号化形式の文字列。
    // uプレフィックスを付けた文字列リテラルはchar16_tのシーケンスとなる。
    // Uプレフィックスを付けた文字列リテラルはchar32_tのシーケンスとなる。
    char16_t s16[] = u"あいうえお";
    char32_t s32[] = U"あいうえお";

    // 文字列中にユニバーサルキャラクタ名を直接入力できる。
    // \uからはじめて4桁、もしくは\Uからはじめて8桁がユニバーサルキャラクタ名として扱われる。
    char16_t s[] = u"\U00020BB7野家"; // 𠮷野家

ただし、C++11時点で、標準ライブラリでは`char16_t`と`char32_t`の入出力はサポートしない。そのため、それらの文字・文字列はシステムの文字コードに変換して入出力する必要がある。

## 仕様

### char16_t型、char32_t型の文字・文字列リテラルと文字コード

- `char16_t`と`char32_t`は予約語(キーワード)である。
- `u`プレフィックスが付く文字リテラルの型は`char16_t`であり、`u`プレフィックスが付く文字列リテラルの要素型は`char16_t`である。
  - ひとつの文字を含む`char16_t`リテラルの値は、ひとつの16ビットコードポイントで表現できるISO 10646のコードポイント値と同じである。
  - ひとつの値を16ビットで表現できない場合、プログラムは不適格となる。
  - 複数の文字を含む`char16_t`文字リテラルは不適格である。
  - `char16_t`文字リテラルが、基本文字集合とユニバーサルキャラクタ名より多くを含む場合は実装定義となる。
  - `char16_t`の場合、ひとつの文字がひとつ以上の`char16_t`を生成することがある。その文字はサロゲートペアと呼ばれる。
  - `char16_t`型の文字列リテラルは、静的ストレージに配置される。
- `U`プレフィックスが付く文字リテラルの型は`char32_t`であり、`U`プレフィックスが付く文字列リテラルの要素型は`char32_t`である。
  - ひとつの文字を含む`char32_t`リテラルの値は、ひとつの32ビットコードポイントで表現できるISO 10646のコードポイント値と同じである。
  - ひとつの値を32ビットで表現できない場合、プログラムは不適格となる。
  - 複数の文字を含む`char32_t`文字リテラルは不適格である。
  - `char32_t`文字リテラルが、基本文字集合とユニバーサルキャラクタ名より多くを含む場合は実装定義となる。
  - `char32_t`型の文字列リテラルは、静的ストレージに配置される。
- `char16_t`と`char32_t`はそれぞれ、`<cstdint>`ヘッダで定義される`uint_least16_t`と`uint_least32_t`と、サイズ、符号の有無、アライメントが同じである。
- `<cuchar>`ヘッダでマクロ`__STDC_UTF_16__`が定義される場合、`char16_t`型の値はUTF-16の妥当なコードポイントを持つ。そうでない場合、`char16_t`型の値は実装定義の文字コードとなる。
- `<cuchar>`ヘッダでマクロ`__STDC_UTF_32__`が定義される場合、`char32_t`型の値はUTF-32の妥当なコードポイントを持つ。そうでない場合、`char32_t`型の値は実装定義の文字コードとなる。

### ユニバーサルキャラクタ名

- `char16_t`文字・文字列リテラルと`char32_t`文字・文字列リテラルのなかには、UCS／Unicodeのユニバーサルキャラクタ名を直接記述できる。たとえば、`char16_t`文字リテラル`u'\u215A'`はU+215Aコードポイントの文字である`'⅚'` (VULGAR FRACTION FIVE SIXTHS) を表す。`\u`の場合は16進数で4桁固定のユニバーサルキャラクタ名を、`\U`の場合は16進数で8桁固定のユニバーサルキャラクタ名を記述する。

      #include <cassert>

      int main()
      {
        char16_t a = u'\u215A';
        char16_t b = u'⅚';

        assert(a == b);
      }

- `char16_t`と`char32_t`のユニバーサルキャラクタ名は、`[0x0, 0x10FFFF]`の範囲内であること。

### 参照するUCSの規格

C++11時点の規格では、UCSの規格としてISO/IEC 10646-1:1993を参照する。

## 例

### サロゲートペアを含む状況

    #include <cassert>
    #include <string>

    int main()
    {
      std::u16string s16 = u"𠮷野家";
      std::u32string s32 = U"𠮷野家";

      assert(s16.size() == 4); // サロゲートペアを含むので1文字分多い
      assert(s32.size() == 3); // UTF-32にサロゲートペアはない
    }

#### 出力

### UTF-32に文字コード変換して簡易的にコードポイント数を算出する

    #include <iostream>
    #include <string>
    #include <locale>
    #include <codecvt>

    int main()
    {
      // UTF-8とUTF-32の相互変換を行うコンバーター
      std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;

      // UTF-8からUTF-32に変換
      std::string u8str = u8"あいうえお";
      std::u32string u32str = converter.from_bytes(u8str);

      // コードポイント数を取得
      std::size_t codepoint_count = u32str.size();
      std::cout << codepoint_count << std::endl;
    }

#### 出力

    5

## この機能が必要になった背景・経緯

この機能が提案された2004年当時にはすでにUCS／Unicodeが広く普及していた。多くのユーザーがその文字コードを扱うことを望んでいたために、標準C++で正式にサポートすることとなった。

## 関連項目

- `u16string`
- `u32string`
- `wstring_convert`
- C++11 UTF-8文字列リテラル
- C++20 UTF-8エンコーディングされた文字の型として`char8_t`を追加
- C++20 `char16_t`と`char32_t`の文字・文字列リテラルを、文字コードUTF-16/32に規定
- ostream `operator<<`
- C++23 名前付きユニバーサルキャラクタ名
- C++23 エスケープシーケンスの区切り

## 参照

- WG14 N1040 Extensions for the programming language C to support new character data types
- N1628 Extensions for the Programming Language C++ to Support New Character Data Types
- N1823 New Character Types in C++
- N1955 New Character Types in C++
- N2018 New Character Types in C++
- N2149 New Character Types in C++
- N2249 New Character Types in C++
- N2170 Universal Character Names in Literals