GUST NOTCH? DIARY

TCHAR とマルチバイト文字とユニコード

Windows では、TCHAR という型がある。これは、文字セットが Unicode の場合とマルチバイト文字セットの場合とでコードを共通化できるようにするための仕組みである。TCHAR で宣言しておいて _stprintf などの関数を使っておけば、Unicode の時は wchar_t と swprintf を、マルチバイト文字の場合は char と sprintf を利用したことになるようによきに計らってくれる。

ちなみに、文字列リテラルには _TEXT("xxx") というのを使えば、よきに計らってくれる。これは、プリプロセッサで以下のような感じで定義されているらしい。

#ifdef _UNICODE
#define __T(x) L ## x
#else /* ndef _UNICODE */
#define __T(x) x
#endif
 
#define _TEXT(x) __T(x)

こんな演算子があったとは知らなんだ。Unicode の場合は L"xxx" になり、そうでない場合は "xxx" になるというわけだ。

さてさて、最近の VisualStudio では、普通にコンソールアプリのプロジェクトを作るとメインが以下のようになる。

int _tmain(int argc, _TCHAR* argv[])

デフォルトでは Unicode 文字セットを使う状態になっているので、これだと argv に日本語の引数を渡したときに、自動的に内部で Unicode 文字列 (wchar_t *argv[]) として取り込まれる。
これらの引数は、MessageBox の引数にはそのまま使えるが、printf デバッグとかしようとすると文字化けしてしまう。これは、UNICODE ストリームへの出力がサポートされていないためのようだ。なので、コンソールに出したい場合は、WideCharToMultiByte を使う必要がある。
プログラム内で閉じていればいいのだが、入出力が絡むと TCHAR の便利さが一気になくなるような気がする。Unicode テキストファイルを読み込むにはバイナリモードにしないといけないらしいがうまくいかない。SJIS テキストを読み込む時は、受け皿が TCHAR でUnicode 文字セットだとうまくいかない。結局 char で宣言した配列で受けて、適宜変換してやる必要があるようだ。
なんかうまい方法はないんだろうか?