1

符号なし文字にキャストされたときに、UCHAR_MAXがINT_MAXより大きい{INT_MAX + 1...UCHAR_MAX}の間にある文字値を処理する適切な方法は何ですか。

int is_digit(char c) {
    unsigned char uchar = c;
    if(uchar > INT_MAX)
        return MAYBE;
    return isdigit((int)uchar) ? YES : NO;
}
4

2 に答える 2

1

唯一の方法は、マシンにいる場合UCHAR_MAXよりも大きくなります; つまり、 where には と同じ数のビットがあります。これらのマシンでは、= ≥ .INT_MAXsizeof(int) == 1charintUCHAR_MAXUINT_MAXINT_MAX

32 ビット (またはそれ以上) のマシンでは、これが問題になることはほとんどありません。変数の値がcテキスト ソースから取得されている限り、オーバーフローを引き起こすことがわかっているテキスト エンコーディングはありません。「UTF-32」でも、下位 21 ビットのみがアクティブになります。(実際には、奇妙なシステムについて話し合っているので、これはsizeof(int)= 1 かつCHAR_BIT≥ 22 のマシンで機能すると言わなければなりません ☺)

それでもそのようなマシンでより大きいis_digit()引数が渡された場合、それはテキスト ソースからのものではありません。未定義の動作は、文字以外のデータを変数に入れることの結果であり、実装が原因ではなく、常にプログラマーが行ったものです。cINT_MAXchar

これが問題になる可能性があるシステムがあります: 16 ビットcharおよびint、システムは 16 ビット文字コード (たとえば、UTF-16) を使用し、上位ビットを設定できます。charそのような場合は、まさにこの理由から、プレーンを署名付きとして定義することが実装に値します。signed を使用charすると、(signed) に昇格し、関数のファミリにint安全に渡すことができます。unsigned では、に昇格しis*()、signed へのキャストは未定義になる可能性があります。charunsignedintint

そのようなシステムでは、コードは確かに壊れていますが、完全に不要な変換と危険な(このシステムでは)キャストに対するあなた自身の責任です。unsigned char(int)uchar

要約すると、システムでsizeof(int) == 1は、すべてのコードポイントが変数に格納されている場合、(引数を期待する) 関数charに安全に渡すことができることを保証する実装の責任があります。これはいつでも実行できます。コードポイントではない変数に何かを格納してそれを渡した場合、未定義の動作の責任はあなたとあなただけにあります。ctype.hintcharis*()

于 2012-02-02T16:11:18.517 に答える
0

Unicode 文字セット (一般的に使用される最大のもの) には、0 から 0x10ffff までの文字コードがあります。そのため、文字コードが INT_MAX よりも大きくなる唯一の可能性intは、16 ビット タイプ (具体的には 22 ビット未満) の場合です。その場合、単に文字コードを に格納することはできませんint

int32 ビット型 (または少なくとも 22 ビット) の場合、 にキャストしても文字コードはオーバーフローしませんint

于 2010-06-28T22:28:06.100 に答える