The following code compiles without warning:
std::uint16_t a = 12;
std::uint16_t b = a & 0x003f;
However, performing a bit shift along with the bitwise and leads to an 'implicit cast warning':
std::uint16_t b = (a & 0x003f) << 10; // Warning generated.
Both gcc and clang complain that there is an implicit conversion from int
to uint16_t
, yet I fail to see why introducing the bit shift would cause the right hand expression to suddenly evaluate to an int
.
EDIT: For clang, I compiled with the -std=c++14 -Weverything
flags; for gcc, I compiled with the -std=c++14 -Wall -Wconversion
flags.
Logical bit shifting may be useful for multiplying or dividing unsigned integers by powers of two. For example, if the value "0001" or "1" is shifted left, it becomes "0010" or "2," shifted to the left again it becomes "0100," or "4." Shifting to the right has an opposite effect of dividing the value by two per shift.
The bitwise shift operators are the right-shift operator (>>), which moves the bits of shift_expression to the right, and the left-shift operator (<<), which moves the bits of shift_expression to the left.
The Java programming language also provides operators that perform bitwise and bit shift operations on integral types.
Doing any arithmetic with integer types always is preceded by promotion to at least (sometimes, but not in this case using gcc, unsigned
) int
. As you can see by this example, this applies to you first, warning-less variant too.
The probably best way to get around these (admittedly often surprising) integer promotion rules would be to use an unsigned int
(or uint32_t
on common platforms) from the get go.
If you cannot or don't want to use the bigger type, you can just static_cast
the result of the whole expression back to std::uint16_t
:
std::uint16_t b = static_cast<std::uint16_t>((a & 0x003f) << 10);
This will correctly result in the RHS-value mod 2^16.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With