88

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

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

4

1 に答える 1

59

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

No.\xは何にでも使用できますが\u\U特にUTFエンコードされた文字列でのみ使用できます。ただし、UTFでエンコードされた文字列の場合は、必要に応じ\u\U使用できます。

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

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

使用されるコードユニットの数は、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でエンコードされた文字列を格納できます。charしかし、彼らはそれらを、、、char16_tまたはchar32_t;のシーケンスとしてのみ考えることができます。それらを特定のメカニズムでエンコードされた一連のUnicodeコードポイントと考えることはできません。basic_string::length()コードポイントではなく、コードユニットの数を返します。そして明らかに、C標準ライブラリの文字列関数はまったく役に立たない

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

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

于 2011-07-23T00:34:07.670 に答える