Version 11.06
Unicode
「今回は、文字コードのひとつ、 Unicode について紹介します」
『ゆにこーど?』
「そう。えーっと、文字コードについて簡単にまとめておくね。主な文字
コードには次のようなものがあります」
ASCII : 日本語のない文字コード。 Unicode 以外はこれを含んでます。
Shift JIS : Windows で日本語を扱うときはこれ。
JIS : 普段は使わないけどメールを送るときにはこれに変換する。
EUC : Unix 用。ホームページの中にはこれで書かれてるものも。
Unicode : 2バイト変数で1文字を扱う。微妙な立場。
UTF-8 : 1〜3バイトで文字を表す。これからの本命?
『いっぱいある……』
「って言っても今回はこれらには触れません」
『今回は Unicode なんだよね』
「そう。 Unicode そのものには次のような特徴があります」
・2バイト変数で1つの文字を表現する。
・あらゆる国の文字を(一応)表現できる。
・ C++ では(一応)簡単に使用できる。
・ Windows では NT 、 2000 、 XP が対応している。
「となっています。ひとつひとつ見ていくと」
・2バイト変数で1つの文字を表現する。
『あれ? Shift JIS も2バイトだったじゃない』
「あれは char がふたつだったでしょ。 Unicode の場合、 wchar_t ってい
う違う型を使います。で、これは」
typedef unsigned short wchar_t;
「ってなってます」
『 unsigned short と同じ、そっか、 short だから2バイトなんだ』
「このおかげで Unicode だとリードバイトとかトレイルバイトを気にしな
くていいんです」
『それいい! 変数の中にリードバイトとトレイルバイトの両方入ってるわ
けだから、区別しようがないんだもんね』
「そういうこと。これがまず Unicode のメリットのひとつ。次は」
・あらゆる国の文字を(一応)表現できる。
『何この〈一応〉って』
「 Unicode は2バイトだから、文字は何種類表せる?」
『 short だから……65535通りだね』
「そう。それだけあるから、日本と言わずありとあらゆる国のありとあらゆ
る文字を表せるんです」
『それってすごい……』
「んだけど、実は65535通りじゃ足りなかったんです」
『へ?』
「漢字みたいにすごく文字が多いものは全部表しきれなかったり、似た字が
ひとつにまとめられちゃったりしたんです」
『似た字がひとつにって……たとえば〈人〉と〈入〉とか?』
「あー、ううん、同じ国の文字はそうならなかったんだけど、日本の漢字と
中国の漢字で、見た目はちょっと違う、くらいのものが……」
『いっしょくた……?』
「そういうこと。これが Unicode が嫌われてる一番の理由かな」
『嫌われてるの?』
「微妙、だけどね。プログラミング言語によってはこれが標準のものもある
し」
『へー』
「さて次」
・ C++ では(一応)簡単に使用できる。
『また一応……』
「とりあえず、実際に使ってみます」
void UseUnicode()
{
wchar_t pwch[] = L"ABCあいう";
OutputDebugStringW( pwch );
// ABCあいう
}
『お! 簡単にできたじゃない。えっと、違ってる部分は……まずさっきの
wchar_t を使ってるね』
「そう、 Unicode は char の代わりに wchar_t を使うから」
『次は……あ、 L って付いてる』
「そう。 "" で囲まれた文字列を Unicode 化する場合には、その先頭に L
を付けます」
『付けないとダメ?』
「だめ。コンパイルエラーになっちゃうから。 Version 5.06 ( No.071 )
で〈 "" で囲まれた文字列は char のポインタになる〉って入ったでしょ」
『うん、言われた。あっ、そっか、それだと wchar_t と違っちゃうから』
「そういうこと。 L を付けると "" が wchar_t のポインタになるんです」
『そうしないと型が違っちゃうわけね』
「そういうこと。あともうひとつ違うところがあるんだけど」
『えーっと……あ! W が付いてる!』
「そう、いつもは OutputDebugString() なのに OutputDebugStringW() を
使ってます」
『これも Unicode 用、ってゆーか、引数が wchar_t のポインタを受けると
か?』
「そういうこと。だから、 Unicode を使う時にはこっちを使わなくちゃい
けないんです」
『めんどい……』
「ところが、実は面倒じゃないんです」
『へ?』
「 API には実は3種類あるんです。たとえばこの OutputDebugString() の
系統だと」
OutputDebugString()
OutputDebugStringA()
OutputDebugStringW()
「の3種類」
『ウソ。いつのまにそんなに……』
「まず OutputDebugStringW() 、この W が付いてるのは Unicode 用。逆に
OutputDebugStringA() が付いてるのは普通の Shift JIS 用」
『あれ? OutputDebugString() がそうなんじゃないの? じゃあなんなの
いったい』
「 OutputDebugString() は実は OutputDebugStringA() にも
OutputDebugStringW() にもなるんです。実は OutputDebugString は、普段
は #define で OutputDebugStringA() に置き換えられているんです」
『ってことは、 OutputDebugString() を使ってると思ってたら実は
OutputDebugStringA() を使ってたってわけね』
「そういうこと。で」
#define _Unicode
「ってすると、 OutputDebugString() が今度は OutputDebugStringW() に
置き換わるようになるんです」
『おお! つまり、 OutputDebugString() を使ってれば、いつでも変えら
れるってわけね』
「そういうこと。ちなみにこういうふうに切り替えるために使うマクロにつ
いては Version 6.06 ( No.106 ) を参照ってことで」
『質問!』
「はい火美ちゃん」
『 W とか A ってなんの略?』
「 W は Wide 。2バイトで1文字を表すから〈ワイド〉ってことでそう
なってるみたい。 wchar_t の w もそうだし。 A は ASCII の A 」
『そっちは簡単な理由ね……』
「で、話を戻して。実はこのどっちも使える機能は、 wchat_t にも L にも
あるんです。それを使って書いてみるとこんな感じ」
void UseUnicode()
{
TCHAR pwch[] = _T( "ABCあいう" );
OutputDebugString( pwch );
}
『えっと、 wchar_t が TCHAR に、 L が _T() に……あ! この _T って
よく見かける!』
「サンプルコードとかによく使われてるかな。こうしておけば、 _Unicode
を #define するだけで Unicode が使えます」
『へー』
「ついでに書くとランタイムにも同じようなのがあって」
strcpy : 標準。一応 ASCII 専用。
wcscpy : Unicode 専用。
_mbscpy : 一応 Shift JIS 用。
_tcscpy : _Unicode が #define されてたら wcscpy 。
そうでないなら _mbscpy 。
『つまり、さっきの例で言えば _tcscpy を使うべきってことね』
「そういうこと。そうすれば自動的に切り替えてくれるからね」
『質問!』
「はい火美ちゃん」
『 T ってなんの略?』
「たぶん Text の T 。 _T は _TEXT って書くこともできるから」
『もうひとつ質問! なんでこれ、今まで教えてくんなかったの?』
「色々理由があって、まずはこれ」
・ Windows では NT 、 2000 、 XP が対応している。
『さっき言ってたのの最後のね』
「これはつまり、 Windows95 とか Windows98 とか WindowsMe では使えな
いってことなんです」
『げげ! 使えないってどういうこと??』
「 W が付いた API 、あることはあるんだけど中身が入ってないってこと」
『それじゃダメね……』
「だから実際には使えないのも同じ。それに、一番最初から教えるのにこう
いうよく分からないのは含めたくなかったからね」
『確かに _T とかいっぱいあるとわかんないね……』
「というか……まぁ僕の知ってる限り、実際に Unicode 版を使ってるのっ
て知らない」
『便利そうなのに』
「 C++ ではなじみないから、難しいかも。さて、最後に」
wchar_t pwch[] = L"ABCあいう";
「これが、メモリ上ではどう入ってるのか確認します。ブレークポイント付
けてアドレス調べて、メモリ直接見てください」
『いつものパターンね』
「そうすると」
A B C あ い う \0
41 00 42 00 43 00 42 30 44 30 46 30 00 00
「ってなってます」
『あ、そっか、2バイトずつってことは、 ASCII の A とか B とかもそう
入ってるんだ。……あれ?』
A
41 00
『ってこと? なんか変くない?』
「 Version 4.07 ( No.057 ) で説明したバイトオーダーがあるから」
『げ! こんなとこにもあの面倒なのが!』
「で、バイトオーダーって OS 毎に違うんだよね。その辺もややこしいから
とりあえず使わない方がいいかも」
/*
Preview Next Story!
*/
『なんかすごく便利そうだったのに……』
「これは Unicode が悪いって言うより C++ が悪いかな」
『え? どうして?』
「他の言語だと Unicode が標準っていうのもあるから」
『え〜? ずるい〜』
「というわけで次回」
< Version 11.07 1バイト文字と2バイト文字 >
『につづく!』
「まぁいいことばかりじゃないんだよね、これが……」
『そなの?』
「文字コード関係は、はまると怖いよ、ほんと……」