Integer types smaller than int
are promoted when an operation is performed on them. If all values of the original type can be represented as an int
, the value of the smaller type is converted to an int
; otherwise, it is converted to an unsigned int
(see INT02-C. Understand integer conversion rules). If the conversion is to a wider type, the original value is zero-extended for unsigned values or zerosign-extended for signed types. Arithmetic operations performed on ints yield the same values as on chars and shorts (at least in the low-order bits). However, bitwise operations may have unexpected results.
...
Code Block | ||
---|---|---|
| ||
uint8_t port = 0x5aU0x5a; uint8_t result_8 = ( ~port ) >> 4; |
In this example, a bitwise complement of port
is negated, first computed and then shifted 4 bits to the right. If both of these operations were performed on a an 8-bit unsigned integer, then result_8
would have the value 0x0aU
0x0a
. However, port
will first be promoted to a 32-bit integer (signed or unsigned, depending on implementation) signed int
, with the following results (on a typical architecture where type int
is 32 bits wide):
Expression | Type | Value | Notes |
---|---|---|---|
| | | |
| | |
|
| | | Whether or not value is negative is implementation-defined. |
| | |
|
Compliant Solution
In this compliant solution, we truncate the negation back down to 8 bits. Consequently, result_8
receives the expected value of 0x0aU
.
Code Block | ||
---|---|---|
| ||
uint8_t port = 0x5aU0x5a; uint8_t result_8 = (uint8_t) (~port) >> 4; |
...