UNICODE互換プログラムの作成について

またまた移植の話です。今度はUNICODEに関する話題です。

UNICODEはWinNT系でNativeとなる文字コードです。一応ASCII(日本語だとS-JIS)コードも使えますが、

内部的にはUNICODEで扱われているらしいので、今の環境だと速度的にはUNICODE側が有利になります。

もう一つ使用される可能性があるのがUTF-8で、これは主にWebやLinuxで日本語を扱うときに

標準の文字コードとなることが多い文字コードです。これらには以下のような特徴があります。

UNICODE

  • すべて16bit(実は32bitもあったりするけど)のため、文字検索を行いやすい(順方向、逆方向)
  • WinNT系のNativeの文字コードなのでWindows系では速度が向上する
  • メモリ内文字列長と表示文字列長の取得が簡単
  • ASCII文字列だけだと文字列メモリサイズがちょうど2倍になるのでメモリ効率はよくない
  • 半角文字と全角文字の判定がちょっとややこしい
  • LittleEndianとBigEndianの種類が分かれることがあるのでBOMの判定とエンディアン変換が必要になることも

S-JIS

  • 文字列探索はちょっと難しくなる(両方向とも)
  • UNICODEから変換すると変換に失敗するコードが存在する
  • 半角文字と全角文字の判定は文字コードのバイト数を使って簡易判別できる
  • エスケープシーケンス問題が絡むと判別が難しくなる

UTF-8

  • UTF-8はUNICODEをPackしたもの(必ず1:1で対応する)
  • 文字によって1~4byteのばらつきがあって扱いづらい(先頭を見れば何byteかは判別できるが)
  • ASCIIの範囲内で収まるときはASCIIと同じ文字コードとなるので英語圏には有利
  • 文字列探索はS-JISよりも難しくなる(両方向とも) ただし、対象のオクテットが文字コードの先頭かどうかの判断は出来るのでShiftJISより曖昧さはない
  • BOMが定義されているとファイル内の文字が即座にUTF-8と判定できるので便利
  • Linux系などでは半標準の文字コードなのでLinuxへの移植を考えているときは選択肢に入る
  • 旧のランタイム系関数でも処理が一定量可能(これも移植には有利)

VC++を使っていると、UNICODEとMultiByteのコンパイル対応にはマクロを使うことになります。

切り替えに必要な知識としては

  • WinAPIは末尾がAとWになる関数で自動的に変更される
  • 実文字列はTEXTマクロなどを使って切り替えに対応が必要
  • ランタイム系ではtchar.hを使ってマクロによる切り替えが必要
  • STLのstringはtypedefなどを使ってstd::stringとstd::wstringの切り替えが必要
  • 切り替えができない関数(GetProcAddressなど)には文字コードの注意が必要
  • 元々UNICODEしか受け付けない処理(COM系など)にはMultiByteToWideChar/WideCharToMultiByteとlstrcpyW/lstrcpyAの切り替えをうまく使う必要あり

たとえば、stringの切り替えであれば

#include <string>
#ifdef _UNICODE
typedef std::wstring string;
#else
typedef std::string string;
#endif //_UNICODE

というような感じです。

移植できるようにコードを書いていると、この辺の動作が面倒なんですよね~。

私がこの頃リリースしているやつは両対応で書いた上でUNICODEで出すようにしています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

この記事のトラックバック用URL