久々に技術的な話。
ちょっと、仕事でハマったので、共有&メモっておきます。
Visual Studio の C/C++ で、文字列リテラルがビルド後の実行ファイル内で文字コードが何になるかという話。
まず、文字列リテラルですが
printf( "abcdef" );
のようにダブルクォーテーション「"」で囲まれた中身、「abcdef」が文字列リテラルです。
半角アルファベット英数文字ならまったく問題なく、ASCIIコードになります。
問題は全角文字、日本語が入ってきた場合です。
printf( "ほげほげ" );
これを Visual Studio でビルドすると、出来上がった exe の中身は Shift JIS になります。
他の文字コードの選択としては、ワイド文字(UTF-16)があります。
ワイド文字にするには、どうすれば良いかと言いますと。
文字列リテラルの前に接頭辞「L」を付けます。
printf( L"ほげほげ" );
と書けば、UTF-16 になります。
Microsoft としては、ワイド文字=UNICODE と定義している(していた?)ため、これが UNICODE なんですね~。
ここで、
ハマりポイント 1
プロジェクト→プロパティ→構成プロパティ→全般
のところの「文字セット」。
ここでは「設定なし」「Unicode文字セット」「マルチ バイト文字セット」を選択できます。
![とみさんのブログ-文字セットの選択](https://stat.ameba.jp/user_images/20120520/00/tomisams/59/e2/p/t02200040_0704012811982353864.png?caw=800)
この選択は、ここに影響します。
MSDN の記事
Tchar.h における汎用テキストのマッピング
データ型のマップ
にあるように「_t」「_T」の付いた関数呼び出し、あるいは文字列リテラルを「_T()」「_TEXT()」で囲んでいた場合、呼び出される関数に関しては置換が行われます。
しかし、文字列リテラルに関しては、「Unicode文字セット」を選んだときのみ「L」が付加されワイド文字になりますが、その他の場合は、何も指定されていない状態になります。
つまりは、ASCII および Shift JIS になる訳です。
次に、
ハマりポイント 2
ソースコードの文字コードです。
MSDN の記事
コンパイラおよびリンカーでの Unicode のサポート
に書いてある通り、Visual Studio 2010 では以下の文字コードがソースコードとしてサポートされています。
- BOM付き/BOMなしビッグエンディアンUTF-16
- BOM付き/BOMなしリトルエンディアンUTF-16
- BOM付きUTF-8
ですので、ソースコードを UTF-8 で書けば、ソースコード上では、文字列リテラルは UTF-8 となります。
しかし、コンパイラがビルドする段階で、文字列リテラルは、先ほど書きました通りに処理されて、ASCII+Shift JIS もしくは UTF-16 に変換されるのです。
それでは、
文字列リテラルをUTF-8にする方法
です。
現状でできる方法としては、
ソース .cpp ファイルに以下の pragma を書いておくことで、そのファイル内の文字列リテラルが、すべて UTF-8 で出力されます。
#pragma execution_character_set("utf-8")
もう少し気長に待つことができれば、C++ の次期規格 C++11 にて、接頭辞「u8」というのがサポートされることになっていますので、
printf( u8"ほげほげ" );
と書けば、UTF-8 になります。
すでに、次期 Visual Studio の Visual Studio 11 のベータ版が公開されていますので、試してみるのも良いかもしれません。
ただ、すみませんが、私はまだ試せてないですので。
どなたか、試したらレポください~。
Android携帯からの投稿