The C standard's word on the switch statement

469 Views Asked by At

Consider this code example:

char c = 0xff;
char mask = 0xfe;
switch ((unsigned)(c & mask)) {
case -2: /* do task 1 */ break;
default:   /* do task 2 */
}

Let us assume that CHAR_BIT = 8 and the implementation defined assignment to c and mask is via interpretation of the bit patterns: 11111111 and 11111110, and negative zeros are allowed. The behaviour of this code is therefore:

if char is signed and implementation uses 2's complement, c = -1, mask = -2, c & mask = -2, (unsigned)(c & mask) = UINT_MAX - 1.

if char is signed and implementation uses 1's complement, c = 0, mask = -1, c & mask = 0, (unsigned)(c & mask) = 0. c is zero and not negative zero because C does not allow creation of negative zero via an assignment.

if char is signed and implementation uses signed magnitude, c = -127, mask = -126, c & mask = -126, (unsigned)(c & mask) = UINT_MAX - 125

if char is unsigned c = 255, mask = 254, c & mask = 254, (unsigned)(c & mask) = 254

The case constant -2 is converted to the same type as the controlling expression, so the value is UINT_MAX - 1. Hence it would only match if char is signed and implementation uses 2's complement.

Is this correct according to the C standard or are there additional assumptions that needs to be added?

1

There are 1 best solutions below

5
On

Is this correct according to the C standard

Not really. If char is signed and 8-bit (ie. CHAR_MAX is less than 255), then the line

char c = 0xff;

is implementation-defined. It might do what you say, but it might not.

The C standard 6.3.1.3:

Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.