When I compile this snippet of code in GCC:
uint8_t *reg = ..., newflags = ...;
...
if(*reg == (~(uint8_t)0))
{
newflags |= (1<<2);
newflags |= (1<<7);
}
I get this warning:
warning: comparison is always false due to limited range of data type [-Wtype-limits]
reg
and newflags
are uint8_t *
and uint8_t
types, respectively.
What does this mean? And what do I do to fix it?
~(uint8_t)0
should be (uint8_t)~0
. The operand to ~
, like to other arithmetic operators will be expanded to int
(or to unsigned int
if not all values of the original type are representable in an int
), and int
0
with all bits inverted is outside the range of uint8_t
, except if the implementation supports negative zeroes... Quoting the previous revision of the holy book, 6.5.3.3p4:
- The result of the
~
operator is the bitwise complement of its (promoted) operand (that is, each bit in the result is set if and only if the corresponding bit in the converted operand is not set). The integer promotions are performed on the operand, and the result has the promoted type. If the promoted type is an unsigned type, the expression~E
is equivalent to the maximum value representable in that type minusE
.
For maximal compatibility you should use 0U
instead of 0
to ensure that the value is promoted to unsigned int
instead of int
, but it is exceedingly likely that your computer is a 2's complement one - especially with fixed-width types like uint8_t
- and the behaviour of (uint8_t)~0
will be equivalent to (uint8_t)~0U
(might be different on 1's complement or sign-and-magnitude!).