简体   繁体   中英

Proper modern way of converting two uint8_t into int16_t

What's the proper modern C++ way of converting two uint8t 's into one int16_t that would satisfy clang-tidy?

a[0] << 8 | a[1]

If a[0] >= 128 , I want the result to wrap around, resulting in a negative value.

Clang-Tidy message is

Use of a signed integer operand with a binary bitwise operator

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM