文字列リテラルの文字コード | 終末プログラマ とみさんのメモ帳

久々に技術的な話。


ちょっと、仕事でハマったので、共有&メモっておきます。

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文字セット」「マルチ バイト文字セット」を選択できます。

とみさんのブログ-文字セットの選択

この選択は、ここに影響します。

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携帯からの投稿