19

C と POSIX はどちらも、C/POSIX ロケールに存在する必要がある文字セットは非常に限られていますが、追加の文字が存在することは許可されています。これにより、実装の自由度が大幅に高まります。たとえば、C ロケールですべての Unicode (UTF-8 として) をサポートすることは準拠動作です。ただし、ほとんどの歴史的な実装では、C ロケールは、ISO-8859-1 (Latin-1) または一種の「抽象 8 ビット文字セット」のいずれかの「8 ビットクリーン」シングルバイト文字エンコーディングを持つものとして扱われます。非 ASCII バイトは、特定の ID を持たない抽象文字です。(ただし、後者の場合、コンパイラが を定義する場合__STDC_ISO_10646__、それらは規範的に Unicode 文字、通常は Latin-1 範囲に対応します。)

あまり一般的ではないように思われる別の準拠オプションは、すべての非 ASCII バイトを非文字として扱うことです。つまり、EILSEQエラーで応答します。

私が知りたいのは、C ロケールを実装する際に、これまたはその他の異常なオプションを取る実装があるかどうかです。C ロケールで「上位バイト」を変換しようとするとEILSEQ、(abstract または Latin-1) シングルバイト文字または UTF-8 として扱われる以外の結果になる実装はありますか?

4

4 に答える 4

11

コメントから前の回答まで:

仮定が間違っている可能性がある方法は、基本的に、ポータブル文字セット外のバイトが不正な非文字バイト (EILSEQ) であるか、マルチバイト エンコーディング (UTF-8 またはステートレス レガシー CJK エンコーディング) を構成している可能性があることです。

ここでは、1 つの例を見つけることができます。

Plan 9 は "C" ロケールのみをサポートします。utf.crune.cでわかるように、移植可能な文字以外のルーンが見つかった場合は、単純に別のエンコーディングの文字として処理します。

別の候補としては、Minix*BSD ファミリーがあります (それらがcitrusを使用している限り)。Minix ソース コードでは、文字サイズが 8 ビットでない場合に新しいエンコーディングを検索するfile コマンドも見つけました。

于 2013-04-08T22:21:15.707 に答える
5

面白いことに、最も広く使用されている実装である glibc が、私が探しているものの例であることがわかりました。次の簡単なプログラムを考えてみましょう:

#include <stdlib.h>
#include <stdio.h>
int main()
{
        wchar_t wc = 0;
        int n = mbtowc(&wc, "\x80", 1);
        printf("%d %.4x\n", n, (int)wc);
}

glibc では、出力され-1 0000ます。バイト 0x80 が実装の C/POSIX ロケールの拡張文字である場合、1 に続いてゼロ以外の文字番号が出力されます。

したがって、C/POSIX ロケールが glibc で「8 ビットクリーン」であるという「常識」は、まったく誤りです。何が起こっているかというと、大きな矛盾があります。すべての標準ユーティリティ、正規表現マッチングなどは、(マルチバイト) 文字を によって読み取られるかのように操作するように指定されているにもかかわらず、mbrtowcこれらのユーティリティ/関数の実装は、それらが表示MB_CUR_MAX==1またはLC_CTYPE含まれて"C"いる (または同様の) およびまたは同様charの入力を処理する代わりに、値を直接読み取ります。mbrtowcこれにより、指定された動作 (C/POSIX ロケールの実装が定義されているため、上位バイトを不正なシーケンスとして扱わなければならない) と実装の動作 (ロケール システムを完全にバイパスしている) との間に矛盾が生じます。

とはいえ、質問で要求されたプロパティを持つ他の実装をまだ探しています。

于 2013-04-14T06:24:34.430 に答える
4

「私が知りたいのは、C ロケールを実装する際に、これまたはその他の異常なオプションを取る実装があるかどうかです。」

この質問は、上記の C 標準の制限された文字セットを参照していると想定している「C ロケール」と、特定の実装がどのように実装されているかを参照していると想定している「その他の異常なオプション」が混在しているため、答えるのが非常に困難です。(限定された) C ロケールの文字を処理します。すべての C 実装は、C ロケールを実装する必要があります。それを取り巻く 珍しいオプションはないと思います。

引数として、「... C ロケールを超えた追加/拡張文字を実装する際の異常なオプション」という質問があると仮定しましょう。これは実装に依存する問題になり、すでに述べたように、「実装に大きな自由を残します」。そのため、ターゲットのコンパイラ/ハードウェアを知らなければ、明確に答えることは依然として困難です。

最後の部分:

「... C ロケールで「上位バイト」を変換しようとすると、EILSEQ または (abstract または Latin-1) シングルバイト文字または UTF-8 として処理する以外の結果になりますか?」

C ロケールで上位バイトを変換する代わりに、この SO の質問のようにプログラムでロケールを設定できる場合があります:基になる文字セットは C 実装のみに依存しますか?

このようにして、期待するロケールでキャラクターが確実に処理されるようにすることができます。


char以下のソースに基づいて、C ロケールは最初の 7 ビット (8 ビット型の) のみに関係していると理解しています。

「高バイト」、「Unicode」、および「UTF-8」という用語は、マルチバイトまたはワイド文字エンコーディングのクラスに属し、非常にロケール固有です (最小の C ロケールの範囲を超えています)。(純粋な) C ロケールで「上位バイトを変換」する方法については明確ではありません。明示的に設定されていない場合 (または、上記のリンクのいずれかに記載されているように OS 環境設定からプルする場合)、実装がデフォルト (拡張) ロケールを選択する可能性は十分にあります。

于 2013-04-04T03:40:59.337 に答える