Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving a conversion warning in a compound assignment

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.

like image 673
c0dehunter Avatar asked Jan 27 '26 22:01

c0dehunter


2 Answers

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.

like image 124
2 revs, 2 users 96%caskey Avatar answered Jan 29 '26 11:01

2 revs, 2 users 96%caskey


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.

like image 43
R.. GitHub STOP HELPING ICE Avatar answered Jan 29 '26 11:01

R.. GitHub STOP HELPING ICE



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!