9

C11 では、プレフィックス u8 を持つ新しい文字列リテラルが追加されました。これは、UTF-8 にエンコードされたテキストを含む char の配列を返します。これはどのように可能ですか?通常のcharは署名されていませんか?符号ビットのために、使用する情報が 1 ビット少ないということですか? 私の論理では、UTF-8 テキストの文字列は unsigned char の配列である必要があることを示しています。

4

4 に答える 4

7

ここに潜在的な問題があります:

実装がCHAR_BIT == 8符号-マグニチュード表現を使用する場合char(so charis signed)、UTF-8 が bit-pattern を必要とする場合、それ10000000は負の 0 です。したがって、実装がさらに負の 0 をサポートしない場合、指定された UTF-8 文字には無効な (トラップ) 値が含まれている可能性があり、char問題があります。負のゼロをサポートしている場合でも、ビット パターンが aとビット パターン(ヌル ターミネータ)に10000000等しいという事実は、 a で UTF-8 データを使用するときに問題を引き起こす可能性があります。char00000000char[]

これは、符号付きC11 実装の場合、char符号なしである必要があることを意味すると思います。通常、char署名付きか未署名かは実装次第ですが、もちろん、char署名されているために UTF-8 リテラルを正しく実装できない場合は、実装者は署名なしを選択する必要があります。余談ですが、これは C++ の非 2 の補数実装の場合にずっと当てはまります。C++ ではオブジェクト表現へのアクセスが許可charされているだけでなく、使用されているからです。unsigned charC のみが許可されますunsigned char

2 の補数と 1 の補数では、UTF-8 データに必要なビット パターンは の有効な値でsigned charあるため、実装ではchar符号付きまたは符号なしを自由に作成でき、さらに で UTF-8 文字列を表すことができますchar[]。これは、すべての 256 ビット パターンが有効な 2 の補数の値であり、UTF-8 がバイト11111111(1 の補数の負のゼロ) を使用しないためです。

于 2012-01-11T11:56:47.843 に答える
7

通常のcharは署名されていませんか?

charであるか であるかはsigned、実装に依存しunsignedます。

さらに、符号ビットは「失われる」わけではなく、情報を表すために引き続き使用でき、char必ずしも 8 ビットであるとは限りません (一部のプラットフォームではそれよりも大きい場合があります)。

于 2012-01-11T11:44:37.340 に答える
1

いいえ、それでも符号ビットはビットです! また、UTF-8 仕様自体は、文字が符号なしでなければならないとは言っていません。

PS Wat is kookwekker voor 'n naam?

于 2012-01-11T11:48:14.117 に答える
1

char の符号は重要ではありません。utf8 はシフト操作とマスク操作のみで処理できます (signed 型では面倒かもしれませんが、不可能ではありません)

ポイントごとに説明すると、次のフラグメントには、文字の値に対する算術演算が含まれておらず、シフトとマスクのみが含まれています。

static int eat_utf8(unsigned char *str, unsigned len, unsigned *target)
{
unsigned val = 0;
unsigned todo;

if (!len) return 0;

val = str[0];
if ((val & 0x80) == 0x00) { if (target) *target = val; return 1; }
else if ((val & 0xe0) == 0xc0) { val &= 0x1f; todo = 1; }
else if ((val & 0xf0) == 0xe0) { val &= 0x0f; todo = 2; }
else if ((val & 0xf8) == 0xf0) { val &= 0x07; todo = 3; }
else if ((val & 0xfc) == 0xf8) { val &= 0x03; todo = 4; }
else if ((val & 0xfe) == 0xfc) { val &= 0x01; todo = 5; }
else {  /* Default (Not in the spec) */
        if (target) *target = val;
        return -1; }


len--;str++;
if (todo > len) { return -todo; }

for(len=todo;todo--;) {
        /* For validity checking we should also
        ** test if ((*str & 0xc0) == 0x80) here */
        val <<= 6;
        val |= *str++ & 0x3f;
        }

if (target) *target = val;
return  1+ len;
}
于 2012-01-11T13:06:03.917 に答える