TCHARでいこう。
最近のVisualStudio(VisualC++ 2008)では、プロジェクトのデフォルトがUNICODEになっている。UNICODEと言ってもutf-8ではなくて、UTF-16LEのことだと捉えてください。きょうび、VisualStudioでC++を触ることがこの先、何度あるかわかんないけれども、メモを残しておきます。
charはもう古い。TCHARで行こうぜ。
昔の話では、NT系はUNICODE対応、95系は非対応、とかで、使い分けが存在していた。
TCHAR という char の代わりみたいなものがあって、こう定義されていた。
#ifdef UNICODE typedef WCHAR TCHAR; #else typedef char TCHAR; #endif
コンパイラ(cl)で /D UNICODE がつくかつかないかで、charか、wcharか、切り替わるような仕組みになっている。
NT系ということは、WindowsVistaとか、Windows7とかのことで、もうNT系じゃないWindowsを捜すほうが難しい、という現代の現実を受け止めると、選択肢は実は一つであることがわかってくる。もう全部wcharで書いてしまおうぜ。というのも手かもしれないが、wcharも哀しいかな、UNICODEの定義で実は変わってしまう。
#ifdef UNICODE typedef wchar_t WCHAR; #else typedef short WCHAR; #endif ↑これは正しくない表記。追記参照
9/11追記:
この説明は誤り。コメントで指摘いただいた。こちらを見るとwchar_tをネイティブ型とするか、unsigned shortになるか変化するらしい。
http://msdn.microsoft.com/ja-jp/library/dh8che7s.aspx
というわけで、大人しくTCHARの使い方を覚えたほうがまぁ、今のところ現実的かな、という気がします。
文字列操作関数
msdnを見れば、大抵の関数は、TCHARを使う場合はこの関数で行け、と書いてある。この辺を知っていたら、まずはなんとかなると思う。
普通の関数 | TCHARで使用可 | 説明 |
memset | memset | サイズは文字数で指定 |
strlen | _tcslen | 長さを文字数で取得 |
strncpy | _tcsncpy_s | 文字列をコピー |
strcmp | _tcscmp | 文字列比較 |
sprintf | _stprintf_s | 書式付き文字列作成 |
自然と _s がつく関数を使うことになるのでバッファオーバーフローとか起きにくくなると思う。
_Tマクロ
char型のように文字列は宣言できず、_T()マクロを使う。
char * a = "abcd"; // こうではなく TCHR * a = _T("abcd"); // こう書きましょう
いたるところに、_T() が付きます。最初は見づらいと思いましたが、慣れの問題です。
ファイルIOの注意
UNICODE がつくと、utf-16LE 相当になるようです。LEというのはリトルエンディアンというやつで、テキストファイルを書きこむ時に、最初にこのファイルはリトルエンディアンで読んでね、という意味のBOM(Byte Order Mark)を自分で書く必要があります。
// 既にファイルはCreateFileなどでオープン済みとする BYTE BOMLE[2]; BOMLE[0] = 0xFF; BOMLE[1] = 0xFE; DWORD writesize = 0; WriteFile(hFile, BOMLE, 2, &writesize, NULL);
書き始めにこういう処理があったほうが親切です。というか、メモ帳で見れるファイルにしたければ必須です。
可変長引数
TCHAR環境で使う方法にしばらく悩みました。最終的にこういう感じに落ち着きました。
include <stdargs.h> void my_putf(TCHAR *format, ...) { va_list args; TCHAR buf[1024]; ZeroMemory(buf, 1024); va_start(args, format); _vstprintf_s(buf, 1024, format, args); va_end(args); // あとはいろいろ }
1024文字を超える場合は、こういう手抜きをせずに、必要サイズをmallocで取ってfreeするべきです。MSDNのサンプルはそうなっています。が、TCHARで書かれていないのが惜しい。
http://msdn.microsoft.com/ja-jp/library/xa1a1a6z%28v=vs.80%29.aspx