86

厳密な Unicode プログラミングを行うには、どのような前提条件が必要ですか?

これは、コードで型を使用してはならず、 and を処理できる関数を使用する必要があることを意味しますcharか?wint_twchar_t

このシナリオでマルチバイト文字シーケンスが果たす役割は何ですか?

4

8 に答える 8

43

C99以前

C 標準 (C99) はワイド文字とマルチバイト文字を提供しますが、これらのワイド文字が何を保持できるかについて保証がないため、それらの値は多少制限されます。特定の実装では、それらは有用なサポートを提供しますが、コードが実装間を移動できる必要がある場合、それらが有用であるという保証は不十分です。

その結果、Hans van Eck によって提案されたアプローチ (ICU - International Components for Unicode - ライブラリのラッパーを作成すること) は健全であり、IMO です。

UTF-8 エンコーディングには多くの利点があります。その 1 つは、データをいじらない場合 (たとえば、データを切り捨てるなど)、UTF-8 の複雑さを完全には認識していない関数によってコピーできることです。エンコーディング。これは、絶対に当てはまりませんwchar_t

完全な Unicode は 21 ビット形式です。つまり、Unicode は U+0000 から U+10FFFF までのコード ポイントを予約しています。

UTF-8、UTF-16、および UTF-32 形式 (UTF は Unicode Transformation Format の略です - Unicodeを参照) の便利な点の 1 つは、情報を失うことなく 3 つの表現間で変換できることです。それぞれは、他の人が表すことができるものなら何でも表すことができます。UTF-8 と UTF-16 はどちらもマルチバイト形式です。

UTF-8 はマルチバイト形式であることがよく知られており、文字列内の任意の位置から始まる、文字列内の文字の開始を確実に見つけることを可能にする慎重な構造を備えています。1 バイト文字の上位ビットはゼロに設定されています。マルチバイト文字は、ビット パターン 110、1110、または 11110 (2 バイト、3 バイト、または 4 バイト文字の場合) のいずれかで始まる最初の文字を持ち、後続のバイトは常に 10 で始まります。継続文字は常に範囲 0x80 .. 0xBF。UTF-8 文字は可能な限り最小限の形式で表現する必要があるという規則があります。これらの規則の結果の 1 つは、バイト 0xC0 および 0xC1 (0xF5..0xFF も) が有効な UTF-8 データに表示されないことです。

 U+0000 ..   U+007F  1 byte   0xxx xxxx
 U+0080 ..   U+07FF  2 bytes  110x xxxx   10xx xxxx
 U+0800 ..   U+FFFF  3 bytes  1110 xxxx   10xx xxxx   10xx xxxx
U+10000 .. U+10FFFF  4 bytes  1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx

当初、Unicode は 16 ビットのコード セットであり、すべてが 16 ビットのコード空間に収まることが期待されていました。残念ながら、現実の世界はもっと複雑で、現在の 21 ビット エンコーディングに拡張する必要がありました。

したがって、UTF-16 は「基本多言語面」の単一単位 (16 ビット ワード) コード セットであり、Unicode コード ポイント U+0000 .. U+FFFF を持つ文字を意味しますが、2 つの単位 (32 ビット) を使用します。この範囲外の文字。したがって、UTF-16 エンコーディングで動作するコードは、UTF-8 が必要とするのと同様に、可変幅エンコーディングを処理できなければなりません。ダブルユニット文字のコードはサロゲートと呼ばれます。

サロゲートは、Unicode 値の 2 つの特別な範囲からのコード ポイントであり、UTF-16 で対になったコード単位の先頭および末尾の値として使用するために予約されています。先頭 (高とも呼ばれます) のサロゲートは U+D800 から U+DBFF までであり、末尾 (低) のサロゲートは U+DC00 から U+DFFF までです。これらは文字を直接表すのではなく、ペアとしてのみ表すため、サロゲートと呼ばれます。

もちろん、UTF-32 は、任意の Unicode コード ポイントを 1 つのストレージ ユニットにエンコードできます。計算には効率的ですが、ストレージには効率的ではありません。

ICUおよび Unicodeの Web サイトで、さらに多くの情報を見つけることができます。

C11と<uchar.h>

C11 標準ではルールが変更されましたが、現在 (2017 年半ば) でもすべての実装が変更に追いついているわけではありません。C11 標準は、Unicode サポートの変更点を次のようにまとめています。

  • Unicode 文字と文​​字列 ( <uchar.h>) (当初は ISO/IEC TR 19769:2004 で指定)

以下は、機能の最小限の概要です。仕様には以下が含まれます。

6.4.3 普遍的なキャラクター名

構文
汎用文字名:
    \u hex-quad
    \U hex-quad hex-quad
hex-quad:
    16 進数字 16 進数字 16 進数字 16 進数字

7.28 Unicode ユーティリティ<uchar.h>

ヘッダー<uchar.h>は、Unicode 文字を操作するための型と関数を宣言します。

宣言されている型はmbstate_t(7.29.1 で説明) およびsize_t(7.19 で説明) です。

char16_t

uint_least16_tこれは 16 ビット文字に使用される符号なし整数型であり、 (7.20.1.2 で説明)と同じ型です。と

char32_t

これは 32 ビット文字に使用される符号なし整数型であり、uint_least32_t(7.20.1.2 にも記述されている) と同じ型です。

(相互参照の翻訳: <stddef.h>define size_t、 define 、およびdefine and 。)ヘッダーは、(再開可能な) 変換関数の最小限のセットも定義します<wchar.h>mbstate_t<stdint.h>uint_least16_tuint_least32_t<uchar.h>

  • mbrtoc16()
  • c16rtomb()
  • mbrtoc32()
  • c32rtomb()

\unnnnまたは\U00nnnnnn表記を使用して識別子に使用できる Unicode 文字については、規則があります。識別子でそのような文字のサポートを積極的に有効にする必要がある場合があります。たとえば、GCC では-fextended-identifiersこれらを識別子で許可する必要があります。

macOS Sierra (10.12.5) は、プラットフォームの 1 つにすぎませんが、サポートしていないことに注意してください<uchar.h>

于 2009-02-09T07:00:49.923 に答える
11

このFAQは豊富な情報です。そのページとJoel Spolsky によるこの記事の間で、良いスタートが切れるでしょう。

途中で私がたどり着いた1つの結論:

  • wchar_tWindows では 16 ビットですが、他のプラットフォームでは必ずしも 16 ビットではありません。Windows では必要悪だと思いますが、他の場所ではおそらく回避できるでしょう。Windows で重要な理由は、名前に非 ASCII 文字を含むファイルを使用する必要があるためです (関数の W バージョンと共に)。

  • 文字列を受け取る Windows API は、wchar_tUTF-16 エンコーディングを想定していることに注意してください。これは UCS-2 とは異なることにも注意してください。サロゲート ペアに注意してください。このテスト ページには、啓発的なテストがあります。

  • fopen()Windows でプログラミングしている場合、fread()fwrite()、 などは使用できません。これらchar *は UTF-8 エンコーディングしか使用せず、理解できないためです。携帯性が苦痛になります。

于 2009-02-09T16:34:13.867 に答える
2

私の知る限り、 wchar_t は実装に依存しています (このwiki 記事からわかるように)。そしてそれはユニコードではありません。

于 2009-02-09T06:03:11.167 に答える