2

UTF8では、次の関数を使用して文字(バイトではなく)をカウントするために使用します。

int schars(const char *s)
{
    int i = 0;

    while (*s) {
        if ((*s & 0xc0) != 0x80) i++;
        s++;
    }
    return i;
}

これは、プレーンcharが存在する実装で機能しますunsigned charか?

4

3 に答える 3

3

署名されている場合と同様に、char署名されていない場合も同様に機能します。

符号付き2の補数表現と符号なし表現の両方で、UTF8コードユニットの8番目と7番目のビットは、コードユニットがコードポイントの最初のコードユニットでない10場合に限ります。したがって、各コードポイントの最初のコード単位として1を数えます。

intすべての文字列に文字数を含めるのに十分な大きさの型であるとは限りませんが、気にしないと思います;-)

「キャラクター」は、あいまいな用語である可能性があります。このコードはUnicodeコードポイントをカウントしますが、これは表示可能な文字(「書記素」)と同じではありません。結合マークがアクセントに使用されている場合など、複数のコードポイントが単一の書記素を表す場合があります。Unicode文字列に含まれるコードポイントの数を知るための唯一の実用的な使用法は、UTF-32としてエンコードされたときに占有するバイト数を計算することです。注意すれば、「文字」を処理する必要がある唯一のコードがフォントエンジンに加えて、Unicode正規化や文字エンコードなどの複雑な操作であることを確認できます。

于 2013-01-09T10:16:01.867 に答える
2

そうすべき。

二項演算子のみを使用しており、基になるデータ型が符号付きか符号なしかに関係なく、それらは同じように機能します。唯一の例外は!=演算子かもしれませんが、これをaに置き換えて&から、全体をa !、alaで囲むことができます。

!((*s & 0xc0) & 0x80)

そして、二項演算子だけがあります。

「[ビット単位のANDの]各オペランドは整数型でなければならない」と述べているANSIC規格のセクション3.3.10をチェックすることにより、文字が整数にプロモートされていることを確認できます。

編集

答えを修正します。ANSI C規格の3.3によると、ビット単位の演算は、符号付きと符号なしで同じではありません。

一部の演算子(単項演算子〜、および二項演算子<<、>>、&、^、および|、まとめてビット演算子と呼ばれる)は、整数型のオペランドを持っている必要があります。これらの演算子は、整数の内部表現に依存する値を返すため、符号付き型の実装定義の側面があります。

実際、符号付き整数に対してビット単位の演算を実行することは、ここに考えられるセキュリティホールとしてリストされています。

Visual Studioコンパイラでは、符号付きと符号なしは同じように扱われます(ここを参照)。

このSOの質問unsigned charで説明されているように、メモリのバイト単位の読み取りとメモリの操作を行うために使用する方が適切です。

于 2013-01-09T10:15:48.770 に答える
1

はい、そうなります。

*sint計算が行われる前にに昇格されます。したがって、コードは次のようになります。

if (((int) *s & 0xC0) != 0x80) i++;

また、上記charは署名されていない場合でも機能します。

于 2013-01-09T10:13:56.573 に答える