Here's one way to convert to a uint16_t
(we'll talk about int16_t
later)
constexpr std::uint16_t combine(std::uint8_t a, std::uint8_t b)
{
return static_cast<unsigned>(a) << 8 | static_cast<unsigned>(b);
}
(live demo in C++11)
One way to ensure portability is to first convert the uint8_t
value to unsigned int
to ensure predictable integer promotion. The value is preserved regardless of the type aliased by uint8_t
, because unsigned int
is guaranteed to be capable of holding all nonnegative integers below 256, and the unsigned integer conversion rules guarantee that the value is preserved. Then, the operations are guaranteed to operate on unsigned int
instead of a signed integer type.
Question: why convert to unsigned
? You are mixing types together. Why not convert to uint16_t
directly?
Note that using static_cast<uint16_t>(a)
instead is not a portable solution because an uint16_t
may still be promoted to int
depending on the environment (for example, when uint16_t
is unsigned short
and int
is 32 bits). Converting to unsigned
gives us full control over the integer promotion rules.
Now the OP want to convert this number to int16_t
, resulting in a negative number if a >= 128
. You can be pretty sure you are using a two's complement system if you are actually intending to do this, so a simple static_cast
may suffice. Otherwise, you can use a separate check. Again, a bit weird.