ワイド文字
ワイド文字(ワイドもじ、英: wide character)とは、主にC言語およびC++における文法要素で、1文字あたりのバイト数を通常より多くしたデータ型である。
概要
[編集]C言語やC++の基本実行文字集合は通常、ASCIIのサブセットの文字種からなる。ただし実際の文字コードが何であるかは規定されていない。
漢字のような拡張実行文字集合は、通常マルチバイト文字として扱われるが、1文字を構成するバイト数が可変長であり、本来1つの文字でありながら複数の文字の組(あるいは文字列)として扱わなければならないなどの不便がある。そうした問題を解消するために、1文字を1つの整数値で扱えるようにすることを目指したのがワイド文字である。
wchar_t型
[編集]C言語では1995年の ISO/IEC 9899/AMD1:1995 より、wchar_t
型や <wchar.h>、<wctype.h> などのヘッダーファイルが追加になった。ワイド文字は wchar_t
というデータ型で表現する。char
型を用いた文字および文字列の場合、文字定数 (character constant)[1] および文字列リテラル (string literal)[2] はソースコード中で、例えばそれぞれ「'c'
」および「"str"
」と表記する。これに対応するように、ワイド文字定数は大文字のエルによるプレフィックスL
を付けて「L'c'
」と表記する。同様に、ワイド文字から構成される文字列をワイド文字列と呼び、そのリテラルは「L"str"
」と表記する。従来の文字定数はchar
型ではなくint
型だったが、ワイド文字定数はwchar_t
型を持つ。従来の文字列リテラルはchar[]
型だったが、ワイド文字列リテラルはwchar_t[]
型を持つ。
C言語での wchar_t
は単なるtypedef
によるエイリアス(他の型の別名として定義されている)であるが、C++においてはキーワード(予約語)である。コンパイラによっては、「wchar_t
」を組み込みの型とみなすか否かをコンパイラの設定で切り替えられるものもある[3]。なおC++の場合、文字定数という用語はなく、文字リテラル (character literal) と呼ばれている[4]。文字リテラルはchar
型を持ち、ワイド文字リテラルはwchar_t
型を持つ。文字列リテラルはconst char[]
型を持ち、ワイド文字列リテラルはconst wchar_t[]
型を持つ。
C99 規格や C++98 規格の場合、ワイド文字定数・文字列リテラルには ISO 10646 文字集合の数値で表現するユニバーサル文字名を使用することもできる。
内部表現
[編集]char
型のサイズは常に1バイトであることがC/C++規格で保証される[5]。つまり、sizeof(char) == 1
は常に真である。
一方、wchar_t
型は C および C++ 双方の標準規格において、符号付きの場合は少なくとも-127から+127まで、符号無しの場合は少なくとも0から255までの範囲を表現できる数値型[6]、ということのみ定められている(少なくともchar
型と同じ大きさが必要)。char
がASCIIであるとは限らなかったり、float
やdouble
がIEEE 754の単精度・倍精度であるとは限らなかったりすることと同様に、wchar_t
の内部表現もUnicodeである必要はない。本来はCode Set Independent(符号化集合に独立)なのである。
wchar_t
型のサイズと符号化形式は、例えばWindowsでは2バイト (16ビット) のUTF-16であり、LinuxやmacOSでは4バイト (32ビット) のUTF-32である。しかし、その他の環境でもUnicodeを用いた符号化形式であると誤解されて、あるいは仮定してプログラムが作られることがある[要出典]。そのようなプログラムは、Unicodeを用いた符号化形式とは限らない一般のUnixなどへの移植の際に問題が表面化する。なお、C99より、wchar_t
がUnicodeと互換性のある場合、__STDC_ISO_10646__
が事前定義されると定められている。C++11でもC99互換の定義済みマクロが導入された
[7]。
char16_t, char32_t型
[編集]ワイド文字の問題は、前述のように型のサイズや符号化形式が規定されておらず、プラットフォームおよび処理系依存であることである。Unicodeが普及するにつれて、移植性の問題が表面化してきた。
2011年に改訂された C/C++ の標準規格、C11 と C++11 では、新たに2つの文字型 char16_t
と char32_t
が導入された。これらはそれぞれ UTF-16 と UTF-32 を内部表現とする。u'c'
や U'c'
あるいは u"str"
や U"str"
のように小文字の u
あるいは大文字の U
を前置することで、それぞれ char16_t
と char32_t
の文字定数・文字列リテラルを表現する。また、u8
を前置することで UTF-8 の文字列リテラルを表現する[8]が、C++17まではchar8_t
型は存在せず、従来のchar
型で代用する仕様だった。C++17ではUTF-8の文字リテラルをサポートするようになったが、その型はchar
であった[4]。C++20ではchar8_t
型がサポートされるようになり、UTF-8文字リテラルの型とUTF-8文字列リテラルの型もそれぞれchar8_t
とconst char8_t[]
に仕様変更された[9]。
C言語の場合char16_t
およびchar32_t
はそれぞれuint_least16_t
およびuint_least32_t
のtypedefエイリアスであるが、C++の場合char16_t
およびchar32_t
はキーワードであり、それぞれstd::uint_least16_t
およびstd::uint_least32_t
と同じサイズではあるものの、別の型として規定されている[10]。
いずれの言語においても、char16_t
型のサイズは16ビットよりも大きい可能性があるが、格納される値は16ビット幅である[11]。同様に、char32_t
型のサイズは32ビットよりも大きい可能性があるが、格納される値は32ビット幅である[12]。
D言語
[編集]D言語では、charと別に、次の2つの文字型が用意されている。
- wchar
- UTF-16を格納する16ビットの文字型
- dchar
- UTF-32を格納する32ビットの文字型
脚注
[編集]- ^ 文字定数 - cppreference.com (C)
- ^ 文字列リテラル - cppreference.com (C)
- ^ /Zc:wchar_t (wchar_t Is Native Type) | Microsoft Docs
- ^ a b 文字リテラル - cppreference.com (C++)
- ^ ただし1バイトが8ビットであることは保証されない。バイトあたりのビット数は、<limits.h>/<climits>にてマクロ定数
CHAR_BIT
として定義される。 - ^ JIS X 3010:2003「プログラム言語C」§7.18.3「他の整数型の限界値」WCHAR_MIN, WCHAR_MAX
- ^ C99互換で導入された定義済みマクロ - cpprefjp C++日本語リファレンス
- ^ 文字列リテラル - cppreference.com (C++)
- ^ UTF-8エンコーディングされた文字の型として`char8_t`を追加 [P0482R6] - cpprefjp C++日本語リファレンス
- ^ 基本型 - cppreference.com
- ^ char16_t - cppreference.com
- ^ char32_t - cppreference.com