次のコード
char buffer[BSIZE];
...
if(buffer[0]==0xef)
...
「データ型の範囲が限られているため、比較は常に false です」というコンパイラ警告を表示します。チェックを次のように変更すると、警告が消えます
if(buffer[0]==0xffffffef)
これは非常に直感に反するように感じます。char
16 進数の特定のバイト値に対して aをチェックする正しい方法は何ですか? (無署名にする以外)
次のコード
char buffer[BSIZE];
...
if(buffer[0]==0xef)
...
「データ型の範囲が限られているため、比較は常に false です」というコンパイラ警告を表示します。チェックを次のように変更すると、警告が消えます
if(buffer[0]==0xffffffef)
これは非常に直感に反するように感じます。char
16 進数の特定のバイト値に対して aをチェックする正しい方法は何ですか? (無署名にする以外)
どうしたの:
if (buffer[0] == '\xef')
?
buffer[0] == 0xef
が警告をトリガーする理由と警告をトリガーしない理由を理解するbuffer[0] == 0xffffffef
には、その式で何が起こっているかを正確に理解する必要があります。
まず、==
演算子は、基になる表現ではなく、2 つの式の値0xef
を比較します。これは数値 239 であり、その数値と等しい値のみを比較します。同様0xffffffef
に 4294967279 という数字があり、それと等しいだけと比較されます。
0xef
定数と239
C に違いはありません。どちらも型int
と同じ値を持ちます。char
の範囲が -128 ~ 127 の場合、 を評価するbuffer[0] == 0xef
とbuffer[0]
は に昇格されint
、その値は変更されません。したがって、 と等しいと比較することはできない0xef
ため、警告は正しいです。
ただし、定数と 4294967279の間には潜在的な違いがあります。0xffffffef
10 進数の定数は常に符号付きですが、16 進数の定数は符号なしの場合があります。お使いのシステムでは、符号なしの型を持っているようです - おそらくunsigned int
(値が に格納するには大きすぎますが、 に格納するにはint
十分小さいためunsigned int
)。を評価するbuffer[0] == 0xffffffef
と、buffer[0]
は に昇格しunsigned int
ます。これにより、正の値は変更されませんが、負の値はUINT_MAX + 1
それらに加算することによって変換されます。-128 ~ 127 の範囲を持つ a のchar
場合、プロモートされた値は 0 ~ 127 または 4294967168 ~ 4294967295 のいずれかの範囲になり ます。0xffffffef
この範囲内にあるため、比較で true が返される可能性があります。
数値ではなくビットパターンを保存している場合はunsigned char
、最初に使用する必要があります。または、オブジェクトへのポインタを にキャストして、オブジェクトのビット パターンを検査することもできますunsigned char *
。
if (((unsigned char *)buffer)[0] == 0xef)
(これは、 type の別の変数を使用することで明らかにより便利に行われますunsigned char *
)。
PaulRが言うように、使用することもできます。これは、ビット パターン 0xef を持つオブジェクトが int に変換されたときに持つ値を持つ定数として定義されてbuffer[0] == '\xef'
いるため、機能します。例えば。符号付きの 2 の補数システムでは、値が -17 の定数です。'\xef'
int
char
'\xef'
これは、buffer
コンテンツがタイプであるために発生していchar
ます。それらを作るunsigned char
とうまくいきます:
if ((unsigned char) (buffer[0]) == 0xef)
他の負の数と同じように行います。
if (buffer[0]== -0x6f)
ただし、通常は、データ型としてunsignedcharを使用します。
unsigned char buffer[BSIZE];
...
if(buffer[0]==0xef)
符号付き文字を使用する理由は非常にまれです。さらにまれなのは、さまざまなプラットフォームで符号付きまたは符号なしの「符号なしの文字」を使用する理由です。
理由を明示的に説明するには:char
署名されているか署名されていないかは実装定義です。コンパイラがchar
デフォルトで署名付きとして扱う場合、可能な最大値(127 または)0xef
よりも大きくなるため、比較は常に false になります。したがって、警告。signed char
0x7f
考えられる解決策は、他の回答によって提供されます。