The following code
char buffer[BSIZE];
...
if(buffer[0]==0xef)
...
Gives the compiler warning “comparison is always false due to limited range of data type”.
The warning goes away when I change the check to
if(buffer[0]==0xffffffef)
This feels very counterintuitive. What is the correct way to check a char against a specific byte value in hex? (other than making it unsigned)
To understand why
buffer[0] == 0xeftriggers a warning, andbuffer[0] == 0xffffffefdoes not, you need to understand exactly what’s happening in that expression.Firstly, the
==operator compares the value of two expressions, not the underlying representation –0xefis the number 239, and will only compare equal to that number; likewise0xffffffefis the number 4294967279 and will only compare equal to that.There is no difference between the constants
0xefand239in C: both have typeintand the same value. If yourcharhas the range -128 to 127, then when you evaluatebuffer[0] == 0xefthebuffer[0]is promoted toint, which leaves its value unchanged. It can therefore never compare equal to0xef, so the warning is correct.However, there is potentially a difference between the constants
0xffffffefand 4294967279; decimal constants are always signed, but hexadecimal constant may be unsigned. On your system, it appears to have an unsigned type – probablyunsigned int(because the value is too large to store in anint, but small enough to store in anunsigned int). When you evaluatebuffer[0] == 0xffffffef, thebuffer[0]is promoted tounsigned int. This leaves any positive value unchanged, but negative values are converted by addingUINT_MAX + 1to them; with acharthat has range -128 to 127, the promoted values are in either of the ranges 0 to 127 or 4294967168 to 4294967295.0xffffffeflies within this range, so it is possible for the comparison to return true.If you are storing bit patterns rather than numbers, then you should be using
unsigned charin the first place. Alternatively, you may inspect the bit pattern of an object by casting a pointer to it tounsigned char *:(This is obviously more conveniently done by using a separate variable of type
unsigned char *).As PaulR says, you can also use
buffer[0] == '\xef'– this works because'\xef'is defined to be anintconstant with the value that acharobject with the bit pattern 0xef would have when converted to an int; eg. on a 2s complement system with signed chars,'\xef'is a constant with the value -17.