web-dev-qa-db-ja.com

C ++ 11ではu8文字列リテラルが必要ですか

Wikipedia から:

C++コンパイラでのUnicodeのサポートを強化する目的で、char型の定義が少なくともUTF-8の8ビットコーディングを格納するのに必要なサイズになるように変更されました。

これが移植可能なアプリケーションを書くために正確に何を意味するのかと思っています。これを書くことに違いはありますか

const char[] str = "Test String";

それともこれ?

const char[] str = u8"Test String";

コード内のすべての文字列リテラルに後者を使用しない理由はありますか?

TestString内に非ASCII文字があるとどうなりますか?

22

"Test String"のエンコーディングは、実装定義のシステムエンコーディング(狭い、おそらくマルチバイトのエンコーディング)です。

u8"Test String"のエンコードは常にUTF-8です。

例はひどくわかりません。いくつかのUnicodeリテラル(\U0010FFFFなど)を文字列に含めた場合、それらは常に(UTF-8としてエンコードされて)取得されますが、それらがシステムエンコードされた文字列で表現できるかどうか、はいそれらの値は、実装によって定義されます。

それが役立つ場合は、EBCDICマシンでソースコードを作成していると想像してください。次に、リテラル「テスト文字列」は常にソースファイル自体でEBCDICエンコードされますが、u8- initialized配列にはUTF-8エンコード値が含まれますが、最初の配列にはEBCDICエンコード値が含まれます。

24
Kerrek SB

あなたはウィキペディアを引用します:

C++コンパイラでのUnicodeのサポートを強化する目的で、char型の定義が少なくともUTF-8の8ビットコーディングを格納するのに必要なサイズになるように変更されました。

まあ、「目的」は真実ではありません。 C標準ではcharに必要な範囲のため、charは常に少なくとも8ビットであることが保証されています。つまり、CHAR_BITは常に≥8である必要があります。これは(引用C++ 11§17.5.1.5/ 1)C++標準に「組み込まれています」。

その表現の変更の目的について推測する必要がある場合は、C規格への依存性を知らない読者のために説明するだけです。

u8リテラル接頭辞の効果については、

  • 実行可能ファイル内の文字列のエンコーディングに影響しますが、

  • 残念ながら、それはしないタイプに影響します。

したがって、どちらの場合も"tørrfisk"u8"tørrfisk"char const[n]を取得します。しかし、前者のリテラルでは、エンコーディングはコンパイラーに選択されたものです。 Latin 1(またはWindows ANSI Western)では、文字サイズは8バイト、配列サイズは9です。後者のリテラルでは、エンコーディングはUTF-8であることが保証されており、「ø」はわずかに大きい配列サイズの場合、2バイトまたは3バイト(正確には覚えていません)。

16

コンパイラは、プラットフォームに固有のネイティブエンコーディングを選択します。典型的なPOSIXシステムでは、おそらくASCIIと、おそらくASCIIの範囲外の文字値の環境設定に依存するものを選択します。メインフレームでは、おそらくEBCDICを選択します。ファイルやコマンドラインなどから受け取った文字列の比較は、ネイティブ文字セットでおそらく最もうまく機能します。ただし、UTF-8を使用して明示的にエンコードされたファイルを処理するときは、おそらくu8"..."文字列。

そうは言っても、文字エンコーディングに関連する最近の変更により、CおよびC++での文字列処理の基本的な前提が崩れました。各内部文字オブジェクト(charwchar_tなど)は、1つの文字を表すために使用されます。これは明らかに、各文字オブジェクトが一部の文字のバイトを表すだけのUTF-8文字列には当てはまりません。その結果、すべての文字列操作、文字分類などの関数がこれらの文字列で機能するとは限りません。このような文字列を標準に含めるために処理するための優れたライブラリはありません。

6
Dietmar Kühl

コンパイラの実行文字セットがUTF-8に設定されている場合、u8が使用されているかどうかは、コンパイラがどちらの場合でも文字をUTF-8に変換するためです。

ただし、コンパイラーの実行文字セットがシステムの非UTF8コードページ(Visual C++などのデフォルト)である場合、非ASCII文字はu8は省略されます。たとえば、ワイド文字列への変換はクラッシュします。 VS15の場合:

std::string narrowJapanese("スタークラフト");
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convertWindows;
std::wstring wide = convertWindows.from_bytes(narrowJapanese); // Unhandled C++ exception in xlocbuf.
5
Roi Danton