问题
In my code I have a lot of variable <<= 1;
sentences where variable
is of type uint16_t. The compiler is spitting a warning saying
conversion to 'uint16_t' from 'int' may alter its value [-Wconversion]
How can I resolve it? I could use a long-form notation like variable = (uint16_t)(variable << 1)
- but I'd like to keep the short notation.
回答1:
Based upon my reading of the standard, you can not get away from this warning for this reason:
uint16_t foo;
foo <<= 1;
is equivalent to
uint16_t foo;
foo = foo << 1;
However, this is caught up in the world of "integer promotion".
The value of the "foo << 1
" expression has the type of "foo
", however before the left-shift can be conducted it first must go through "integer promotion;" section 6.3.1.1.2 of the C99 standard specifies: "if an int can represent all values of the original type, the value is converted to an int."
This makes the non-implicit version of your code (with extra parentheses) as follows:
uint16_t foo;
foo = ((int)foo) << 1;
Given the warning you are on a system with either 32 or 64 bit ints (or anything bigger than 16, really), you are indeed shoving a bigger value into a smaller one.
One way around this is to be explicit with your casts like so:
uint16_t foo;
foo = (uint16_t)(foo << 1);
But that means that no, you can not use the shorter bitwise shift assignment operator.
If you really are doing this a bunch, consider making a helper function that makes your code clear and compiles cleanly.
void LS(uint16_t &value, int shift) { // LS means LeftShift
*value = (uint16_t)(*value << shift);
}
LS(&foo, 1);
TL;DR: No, you can't use the short operator and avoid that warning at the same time.
回答2:
You get the warning because variable <<= 1;
is equivalent to:
variable = variable << 1;
where the right-hand side has type int
, not uint16_t
, due to default integer promotions. The best way around this is not to use smaller-than-int
types.
来源:https://stackoverflow.com/questions/18629780/resolving-a-conversion-warning-in-a-compound-assignment