C ++ 11での文字列リテラルのUnicodeエンコーディング


84

関連する質問に続いて、C ++ 11の新しい文字と文字列リテラルタイプについて質問したいと思います。現在、4種類の文字と5種類の文字列リテラルがあるようです。文字タイプ:

char     a =  '\x30';         // character, no semantics
wchar_t  b = L'\xFFEF';       // wide character, no semantics
char16_t c = u'\u00F6';       // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF';   // 32-bit, assumed UCS-4

そして文字列リテラル:

char     A[] =  "Hello\x0A";         // byte string, "narrow encoding"
wchar_t  B[] = L"Hell\xF6\x0A";      // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6";        // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto     E[] = u8"\u00F6\U0010FFFF"; // (3)

質問はこれです:です\x/ \u/\Uすべての文字列型と自由に組み合わせ可能文字参照?すべては、配列リテラルに表示される多くの要素として正確に含まれている、またはにつまり、文字列型、固定幅のある\x/ \u/\U参照バイトの可変数に拡大しますか?ドu""u8""文字列は例えば、セマンティクスをコードしている私が言うことができchar16_t x[] = u"\U0010FFFF"、かつ非BMPコードポイントは、2単位のUTF16シーケンスにエンコードされますか?そして同様にu8?(1)で、孤独な代理人を書くことはでき\uますか?最後に、文字列関数のいずれかがエンコーディングを認識していますか(つまり、文字を認識し、無効なバイトシーケンスを検出できます)?

これは少し自由形式の質問ですが、新しいC ++ 11の新しいUTFエンコーディングおよびタイプ機能の全体像をできるだけ完全に把握したいと思います。


4
GCCはu"\U0010FFFF"サロゲートペアにエンコードします。
kennytm 2011

回答:


56

\ x / \ u / \ U文字参照は、すべての文字列タイプと自由に組み合わせることができますか?

No.\xは何にでも使用できますが\u\U特にUTFでエンコードされた文字列でのみ使用できます。しかし、任意のUTFエンコードされた文字列のために、\uそして\Uあなたが合うように使用することができます。

すべての文字列タイプは固定幅ですか?つまり、配列にはリテラルに表示される要素とまったく同じ数の要素が含まれていますか、それとも\ x / \ u / \ U参照が可変バイト数に展開されますか?

あなたが意味する方法ではありません。\x\u、および\U文字列エンコーディングに基づいて変換されます。これらの「コードユニット」(Unicode用語を使用。Achar16_tはUTF-16コードユニット)の値の数は、含まれている文字列のエンコーディングによって異なります。リテラルu8"\u1024"は、2char秒とヌルターミネータを含む文字列を作成します。リテラルu"\u1024"は、1char16_tとnullターミネータを含む文字列を作成します。

使用されるコードユニットの数は、Unicodeエンコーディングに基づいています。

u ""およびu8 ""文字列にはエンコードセマンティクスがありますか?たとえば、char16_t x [] = u "\ U0010FFFF"と言うことができ、非BMPコードポイントは2ユニットのUTF16シーケンスにエンコードされますか?

u""UTF-16でエンコードされた文字列を作成します。u8""UTF-8でエンコードされた文字列を作成します。それらはUnicode仕様に従ってエンコードされます。

(1)で、\ uで単独の代理を書くことはできますか?

絶対違う。仕様では、\uまたはのコードポイントとしてUTF-16サロゲートペア(0xD800-0xDFFF)を使用することを明示的に禁止してい\Uます。

最後に、文字列関数のいずれかがエンコーディングを認識していますか(つまり、文字を認識し、無効なバイトシーケンスを検出できます)?

絶対違う。さて、言い換えさせてください。

std::basic_stringUnicodeエンコーディングは扱いません。確かに、UTFでエンコードされた文字列を格納できます。しかし、彼らは唯一のシーケンスと考えることができcharchar16_tまたはchar32_t、それらを特定のメカニズムでエンコードされたUnicodeコードポイントのシーケンスと考えることはできません。basic_string::length()コードポイントではなく、コードユニットの数を返します。そして明らかに、C標準ライブラリの文字列関数はまったく役に立たない

ただし、Unicode文字列の「長さ」は、コードポイントの数を意味するものではないことに注意してください。一部のコードポイントは、前のコードポイントと結合する「文字」(残念な名前)を組み合わせています。したがって、複数のコードポイントを1つの視覚的な文字にマップできます。

Iostreamは、実際にはUnicodeでエンコードされた値を読み書きできます。そのためには、ロケールを使用してエンコーディングを指定し、さまざまな場所に適切に埋め込む必要があります。これは口で言うほど簡単ではなく、その方法を示すコードはありません。


7
@フィリップ:いいえ、そうではありません。Unicodeは、それらをUTF-16サロゲート用に特別に予約しています。また、前述のように、C ++ 0xの仕様では、その範囲内のコードポイントを指定しようとすると、コンパイルが失敗することが示されています。
ニコルボーラス2011

12
あなたのリンクは、それらコードポイントであることを証明してます。ウィキペディアを信頼できない場合は、標準の第3章の定義9と10をお読みください。ただし、文字列リテラルのサロゲートコードポイントは、C ++ 0xではルール§2.4/ 2で禁止されています。
フィリップ

1
読んだ後、サロゲートコードポイントが文字列リテラルで受け入れられることも確認しました。
George Kourtis 2014

C11では、\x例えば、U + 1F984のために、何を使用することはできませんが及び、\ X接頭辞では動作しません\uし、\Uクランでは少なくとも、ASCII制御文字を使用することはできません。
MarcusJ 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.