I was getting some odd behaviour out of a switch block today, specifically I was reading a byte from a file and comparing it against certain hex values (text file encoding issue, no big deal). The code looked something like:
char BOM[3] = {0};
b_error = ReadFile (iNCfile, BOM, 3, &lpNumberOfBytesRead, NULL);
switch ( BOM[0] ) {
case 0xef: {
// Byte Order Marker Potentially Indicates UTF-8
if ( ( BOM[1] == 0xBB ) && ( BOM[2] == 0xBF ) ) {
iNCfileEncoding = UTF8;
}
break;
}
}
Which didn’t work, although the debug looked ok. I realized that the switch was promoting the values to integers, and once that clicked in place I was able to match using 0xffffffef in the case statement. Of course the correct solution was to make BOM[] unsigned and now everything promotes and compares as expected.
Can someone briefly explain what was going on in the char -> int promotion that produced 0xffffffef instead of 0x000000ef?
Contrary to the four answers so far, it didn’t.
Rather, you had a negative
charvalue, which as aswitchcondition was promoted to the same negativeintvalue as required byThen with your 32-bit C++ compiler
0xffffffefwas interpreted as anunsigned intliteral, because it’s too large for a 32-bitint, byNow, for the
caselabel,In your case, with signed destination type, the result of the conversion is formally implementation-defined, by
But in practice nearly all compilers use two’s complement representation with no trapping, and so the implementation defined conversion is in your case that the bitpattern
0xffffffefis interpreted as two’s complement specification of a negative value. You can calculate which value by 0xffffffef – 232, because we’re talking 32-bit representation here. Or, since this is just an 8-bit value that’s been sign extended to 32 bits, you can alternatively calculate it as 0xef – 28, where 0xef is the character code point.Cheers & hth.,