3

次のような C++ コードがある場合:

std::string narrow( "This is a narrow source string" );
std::string n2( "Win-1252 (that's the encoding we use for source files): ä,ö,ü,ß,€, ..." );

// What encoding should I pass to Win32's `MultiByteToWideChar` function
// to convert these string to a propoer wchar_t (= UTF-16 on Windows)?

これが cpp ファイルの (暗黙の) エンコーディングである場合、常に Win-1252 と想定できますか? Visual-C++ コンパイラは、ソース ファイルの文字エンコーディングをどのように決定しますか?

たとえば、開発者が「通常の」テキスト ファイルのデフォルトが別のシングル/マルチバイト エンコーディングになっているマシンを使用するとどうなるでしょうか。

エンコーディングは、コードのコンパイルに使用されるマシンの問題だけだと思いますか? つまり、実行可能ファイルがビルドされると、静的文字列を固定の狭いエンコーディングから Windows の UTF-16 wchar_t に変換すると、ユーザーの PC の言語/ロケールに関係なく、常に同じ結果が得られますか?

4

2 に答える 2

5

注: 以下の回答が書かれているため、VC++ はソースおよび実行文字セット エンコーディングの追加オプションを追加しました。ここ を参照してください


ワイド リテラルの場合、VC++ は常に UTF-16 を生成し、ナロー リテラルの場合、VC++ は常にソース エンコーディングからホスト マシン (コンパイラを実行するシステム) で設定された「非 Unicode プログラムのエンコーディング」に変換します。したがって、VC++ がソース エンコーディングを正しく認識している限り、UTF-16 と非 Unicode プログラムのエンコーディングが得られます。

ソースエンコーディングを決定するために、VC++ はいわゆる BOM を検出します。UTF-16 と UTF-8 を認識します。BOM がない場合は、非 Unicode プログラム用のシステムのエンコーディングを使用してソースがエンコードされていると想定します。

これにより、間違ったエンコーディングが使用される場合、文字および文字列リテラルに対してコンパイラによって実行される変換は、ASCII 範囲外の文字に対して間違った値をもたらします。


プログラムがコンパイルされると、はい、データが静的であるため、これらのコンパイル時の変換が行われる限り、ロケールは問題になりません。

ただし、これらの文字列のいずれかをコンソールに出力する場合など、エンコードは他の場合に重要になる場合があります。コンソールが使用しているものに適切な変換を実行するか、使用しているエンコーディングを受け入れるようにコンソールが設定されていることを確認する必要があります。


注意事項#pragma setlocale

#pragma setlocaleワイド リテラルへの変換のみに影響し、ソース エンコーディングの設定やワイド実行エンコーディングの変更による影響はありません。それが実際に行うことは、率直に言って、恐ろしいことです。例として、次のアサーションは失敗します

#pragma setlocale(".1251")
static_assert(L'Я' != L'ß', "wtf...");

ソースに Unicode エンコーディングを使用している場合は、絶対に避ける必要があります。

于 2012-11-29T14:37:18.567 に答える
3

言語仕様は、ソース文字が実装定義の方法でマップされることを単に示しています。その実装の定義が何を示しているかを確認するには、使用しているコンパイラのドキュメントを参照する必要があります。たとえば、Microsoft VisualC++は#pragma setlocaleコードページを指定するために使用します。

于 2012-11-29T14:23:23.430 に答える