ASCII文字列の文字幅は1バイトです(通常8ビット、めったに7,9または他のビット幅)。これは、メモリサイズが非常に小さくて高価な時代の遺産であり、プロセッサはしばしば1命令につき1バイトしか扱うことができない。
簡単に想像できるように、1バイトは、世界中で利用可能なすべてのグリフを保存するのには十分ではありません。中国だけで87.000グリフがあります。 charは通常、(8ビットのバイトで)256のグリフしか扱えません。 ASCIIは、96個のグリフだけでなく、印刷可能でない制御文字として定義される下位の32文字を定義します。これは、英語の上下の文字、数字、およびいくつかの区切りとその他のグリフには十分です。
1バイトより多くのグリフを処理するには、1バイトに基本グリフ、2バイトに他の共通グリフ、3バイト以上にめったにグリフを使用しないでください。この手法はMulti byte char set or Variable-width encodingと呼ばれています。非常に一般的な例はUTF 8です。これは、1文字につき1バイトから4バイトを使用します。これは、ASCII文字セットを1バイトで格納します(したがって、ASCIIと下位互換性もあります)。最上位ビットはスイッチとして定義されます。設定されている場合、他のバイトが続きます。同じことが次のバイトにも適用され、最大4バイトの「チェーン」が形成される。可変幅の文字セットの プロのは、以下のとおりです。フレンドリー8ビットのASCII文字セット
メモリと
できるだけ少ないメモリとして使用する欠点がある:
- 処理するのがより困難でプロセッサが高価です。単純に文字列を繰り返し、各
myString[n]
が1つのグリフを配信すると仮定することはできません。代わりに、より多くのバイトが続く場合は、各バイトを評価する必要があります。
もう1つの方法は、可能なすべてのグリフを保持するのに十分な幅のnバイトからなる固定長ワードに各文字を格納することです。これは固定幅文字セットと呼ばれます。すべての文字は同じ幅です。よく知られている例はUTF32です。これは32ビット幅であり、可能なすべての文字を1つの単語に格納できます。固定幅の文字セットのproとconは、可変幅の文字セットとは明らかに逆です。メモリが重いですが繰り返しが簡単です。
しかし、マイクロソフトでは、UTF32が使用可能になる前でもネイティブ文字セットを選択しました。これらは、少なくとも2バイト(16ビット)の語長を使用するWindowsのcharセットとしてUTF16を使用します。これは、1バイトの文字セットより多くのグリフを格納するのに十分ですが、それらのすべてではありません。これを考慮すると、Microsoftの "マルチバイト"と "Unicode"の区別は、ユニコードの実装もマルチバイト文字セットであるため、今日は少し誤解を招いています。それは良い妥協だと言われる人もいれば、両方の世界の中で最悪だと言う人もいます。とにかく、それはそうです。そして、その時(Windows NT)、これは唯一利用可能なUnicode文字セットであり、この観点から、マルチチャーとUnicodeの区別は当時正しいものでした(Raymond Chenのコメントを参照)。
もちろん、文字列を1つのエンコーディング(UTF8と言う)で別のもの(UTF16と言う)に変換する必要があります。それはMultiByteToWideChar
があなたのために行うもので、WideCharToMultiByte
の逆です。他にもいくつかの変換関数とライブラリがあります。
この変換にはかなりの時間がかかります。結論は:文字列やシステムコールを頻繁に使用する場合は、パフォーマンスのためにオペレーティングシステムのネイティブ文字セットを使用する必要があります。これはUTF16場合。
文字列の処理には、wchar_t
を選択する必要があります.Windowsの場合はUTF16を意味します。残念ながら、wchar_t
の幅は、コンパイラごとに異なる場合があります。 Unixでは通常はUTF32、WindowsではUTF16です。
_MBCS
は、文字セットをマルチバイトとして定義したことを知らせる自動プリプロセッサ定義であり、UNICODE
はUTF16に設定したことを通知します。
あなたもUNICODE
がセットを定義していないプログラムで
wchar_t* wcMsg = L"مرحبا";
MessageBoxW(0, wcMsg, 0, 0);
を書くことができます。 L"
という接頭辞は、文字列がUNICODE
(ワイド文字)の文字列であることを定義しており、システム関数を呼び出すことができます。
残念ながら、あなたは文字セットのサポートはC++ 11で改善されました
char* msg = u8"مرحبا";
MessageBoxA(0, msg, 0, 0);
を書くことができない、ので、あなたはまた、接頭辞u8
でUTF8として文字列を定義することができます。しかし、windows関数は "A"接尾辞はUTF8を理解しません。 (https://stackoverflow.com/a/504789/2328447も参照してください) これは、Windows/Visual StudioでUTF16という別名UNICODEを使用することを示唆しています。 「使用マルチバイト文字セット」または「使用Unicode文字セット」にプロジェクトを設定
は、他の文字に依存する定義の多くを変更します。最も一般的なものは、マクロTCHAR
、_T()
とすべての文字列に依存するWindowsの機能なしあり接尾辞、例えばMessageBox()
あなたが「使用マルチバイト文字を設定する」ために、プロジェクトを設定した場合 (W
またはA
接尾なし)、TCHAR
は_T()
は何に拡大する、char
に展開され、Windowsの機能は、A
Postfixが添付されます。 プロジェクトを「Unicode文字セットを使用する」に設定した場合、TCHAR
はwchar_t
に、_T()
はL
に拡張され、Windows関数にはW
の接尾辞が付きます。
これは
TCHAR* msg = _T("Hello");
MessageBox(0, msg, 0, 0);
を書くことは、マルチバイト文字セットまたはUnicodeのセットの両方をコンパイルすることを、意味しています。これらのトピックに関する包括的なガイドは、MSDNにあります。
残念ながら
TCHAR* msg = _T("مرحبا");
MessageBox(0, msg, 0, 0);
「使用マルチバイト文字セット」が選択された場合、まだ動作しません - Windowsの機能は、まだUTF8をサポートしていない、とあなたも、いくつかのコンパイラの警告を取得します、あなたのためにUnicodeとしてマークされていない文字列に含まれるUnicode文字を定義しています(_T()
はu8
に拡張されません)
OSはutf16でエンコードされた文字列をネイティブ文字列型として使用します。 wchar_tやstd :: wstringを十分に使用せず、ASCII文字列に使用されているのは、プログラマーがMultiByteToWideCharを多く使用する方法です。特に間違っているのではなく、効率的ではありませんが、アラビア語をASCIIでエンコードした文字列で書くことはほとんど望めません。 C + +と非効率的な1つの文やプログラムで使用される2つの単語でなければなりません。 QtのようなUIフレームワークを使用して痛みを軽減することを検討してください。 –
@HansPassant:ありがとう。回答を追加するとどうなりますか?それはとても好意的だろう。 – WonFeiHong
"私はASCII文字列を扱うのに慣れています":それは非常に疑わしいです。 MessageBoxAのようなWin32 API関数の呼び出し、テキストファイルの読み書き、コンソールの読み書き、またはC +ライブラリの使用を行っている場合、CP437のような文字エンコーディングを指定するユーザーの "locale" 、Windows-1252などがありますが、ASCIIではありません。 –