2017-11-23 6 views
2

私は最近Tom Scott from Computerphile talk about UTF-8を見てきたし、それ以降研究のビットは、UTF-8は、バイトごとに次のヘッダーを使用して、最大6バイトの文字をエンコードするために使用することができることを理解する:言語はどのようにしてUTF-8を表現していますか?

0xxx xxxx # 1 Byte character 
110x xxxx # 2 Byte character 
1110 xxxx # 3 Byte character 
1111 0xxx # 4 Byte character 
1111 10xx # 5 Byte character 
1111 110x # 6 Byte character 

そして、 10xx xxxxを使用して余分なバイトを表現しています(私はRFC3629がこれを4バイトまでしか制限しないことを知っています)。

これは、2,164,286の異なる文字が(予約文字を無視して)エンコードできることを理解していますか? Iは、UTF-8でエンコードされた文字列を格納するcharアレイを使用することができ、又はIではなく、各UTFを符号化するためにUTF-32のような固定長符号化を使用し、そのようなunsigned longなどの任意の4バイトのタイプを使用することが理論的に

0xxx xxxx # 7 bits      =>  128 
110x xxxx # 5 bits + 6 bits = 11 bits =>  2,048 
1110 xxxx # 4 bits + 6*2 bits = 16 bits => 65,536 
1111 0xxx # 3 bits + 6*3 bits = 21 bits => 2,097,152 
      #        == 2,164,864 

-8エンコードされた文字ですが、1バイトまたは2バイトでエンコードされたUTF-8文字のみを使用するテキストではメモリが大幅に増加します。

私はstd::stringがUTF-8で保存することができ、これはsizeとバイト長を返すlengthになりますが、UTF-8は、文字の様々な長さを表すことができれば、どのような言語は、(我々は範囲を限定するためにC++を取るよんと信じてこの質問の中でこれらの文字を内部的に符号化します(std::stringなど)。いくつかの制限以下の

+0

からと変換するための責任があるのAPIがあります。例: 'MultiByteToWideChar'と' WideCharToMultiByte'です。 – Raindrop7

+0

@ Raindrop7は真実かもしれませんが、背景に何が起こっているのかという質問に実際には答えません。 –

+0

現在のところ、Unicodeは現在21ビット分のコードポイントしか使用できません(2^16コードポイントの17プレーンのみが実際に指定された、可能な限り32)。 –

答えて

4

UTF-8文字列をバイトのシーケンスである(つまり、char -sまたはC++でuint8_tの、ある)(そのバイトのないすべてのシーケンスが有効なUTF-8文字列です。あなたには、いくつかの文字列を取得する場合UTF-8であると主張する外部から、それを検証する必要があります)。

したがって、std::string -sを使用してUTF-8文字列を表すことができます(ただし、有効なUTF-8であることが条件です)。

これらの上にUTF-8ライブラリ(例:libunistringまたはGlib Unicode Manipulation)を使用することができます。

つまり、UTF-8は、文字列の使用方法(char -s)に関するの規約と見なすことができます。もちろん

は、(例えばstd::stringsize())バイトの数がない UTF-8文字の数であることに注意してください。また、通常のイテレーターを使用してUTF-8文字(またはそれらのUnicodeに相当するもの)を反復することはできません。

UTF-8対応のC++ライブラリ(GtkmmではGlibmm ustring -sなど)、そうでなければUnicode文字列を表すライブラリ(QtではQString -sなど)があります。

ところで、UTF-8(およびUnicode)は、画面や紙に適切にレンダリングするのがかなり複雑です(そのためにはライブラリが必要です)。あなたは、同じ文字列内で、様々な言語(英語、ロシア語、アラビア語、中国語)の組み合わせを使用している場合があります。結合文字(アクセントなど)があるかもしれません。 Unicodeはかなり複雑です(私はほとんどの人間の言葉は知らないので、私はそのほとんどを知りません;私は英語、フランス語、ロシア語しか話すことはできません)いくつかのギリシャ文字を解読することができます。中国語は完全に私にとっては外国語です)。

http://utf8everywhere.org/も参照してください。UTF-8およびUnicodeのウィキペディアも参照してください。

+1

有効なUTF-8を格納するために 'std :: string'を使用すると、他のデータ型ではなくchar型のシーケンスとして格納されます(つまり、' std: :string' **常に**ただ 'char'sのシーケンスを格納するだけです)? –

+4

もちろん。 Unicode文字列(例えば、 'uint32_t')を使うことができます。あなたはおそらくこれをしたくないでしょう。 –

+0

そして、Unicodeの "文字"を1つの "文字"に組み合わせて出力するワームがあります。例éは1文字または2文字です。 –

3

C++標準では正しいUTF8処理については説明していませんが、コードポイント(文字列ではなく実際の文字)で文字列を繰り返し処理できるライブラリがあります。

通常、テキストはバイト配列として保存されます(tagged pointer stringsなどの好奇心のある最適化が可能です)。通常、コードポイントの正しい処理を提供する軽量string viewsがその上に追加されます。例えば、Swiftプログラミング言語employs this technique

又は

文字符号化I代わりに各UTF-8をコードするUTF-32のような固定長符号化を使用し、そのような符号なし限り、任意 4バイトのタイプを使用することができるとして

C++ 11は、便宜上、std::u8string,std::u16stringおよびstd::u32stringを提供しています。 wchar_tのサイズは、標準で定義されているのではなく、コンパイラによって定義されているので、移植可能なコードでは一般的に避けるべきstd::wstringもあります。

2

あなたは正しいポイントにまっすぐです。私が知っている限り、C++はUTF-8を表現していません。したがって、これは単なる慣習であり、実際にそれを表現するものは、UTF-8を生成し消費するものです。

UTF-8はバイトの周りに配置されているため、std :: stringなどのC++のツールを使用できます。これは単なるバイト配列です。 もちろん、標準を認識していないランダムなライブラリに文字列を送るだけであれば、多くのことが間違ってくる可能性があります。ここでの答えのいくつかで言及されているような文字列のサイズではあるが、さらに悪いことに、ASCII以外の文字は、それらの文字に2バイト以上の文字が含まれているため、奇妙な動作を引き起こす可能性が非常に高いです。

UTF-8に関する素晴らしい点は、値128までのすべての文字(すべての英文字を含む)について同じ表現を持つことです。このため、文字列のプロデューサがUTF-8を認識していないにもかかわらず、その文字列のコンシューマが動作しても、動作は変わりません。

このジョブを既に実行しているライブラリが多数あり、UTF-8文字列の特殊な型を提供するか、std :: stringをUTF-8文字列として読み込みます。標準自体は、各文字がstd::u8string,std::u16stringstd::u32stringなどの1バイト以上の文字列である文字列を提供しますが、この規格では文字サイズが異なるため、UTF-8の場合は本当に役に立ちません。

もネット上で文字列を渡すときあなたは何をすべきかをカバーし、このトピックに関する最終的に非常に良い記事:The Absoultly minimum every developer must know about unicode

関連する問題