Вот один из способов преобразования в uint16_t
(мы поговорим о int16_t
позже)
constexpr std::uint16_t combine(std::uint8_t a, std::uint8_t b)
{
return static_cast<unsigned>(a) << 8 | static_cast<unsigned>(b);
}
(демонстрация на C++11)
Один из способов обеспечить переносимость — сначала преобразовать значение uint8_t
в unsigned int
, чтобы обеспечить предсказуемое целочисленное продвижение. Значение сохраняется независимо от типа с псевдонимом uint8_t
, потому что unsigned int
гарантированно способен содержать все неотрицательные целые числа ниже 256, а правила преобразования целых чисел без знака гарантируют сохранение значения. Тогда операции гарантированно будут работать с unsigned int
вместо целочисленного типа со знаком.
Вопрос: зачем переходить на unsigned
? Вы смешиваете типы. Почему бы не преобразовать в uint16_t
напрямую?
Обратите внимание, что использование вместо этого static_cast<uint16_t>(a)
не является не переносимым решением, поскольку uint16_t
все еще может быть повышено до int
в зависимости от среды (например, когда uint16_t
равно unsigned short
, а int
равно 32 битам). Преобразование в unsigned
дает нам полный контроль над правилами продвижения целых чисел.
Теперь OP хочет преобразовать это число в int16_t
, в результате чего получится отрицательное число, если a >= 128
. Вы можете быть уверены, что используете систему с дополнением до двух, если вы действительно собираетесь это сделать, поэтому простого static_cast
может быть достаточно. В противном случае можно использовать отдельную проверку. Опять же, немного странно.
person
L. F.
schedule
02.08.2019
a[0]
кint16_t
до сдвига влево, иначе вы в конечном итоге сдвинетеuint8_t
влево на 8 бит и потеряете биты. - person Jeremy Friesner   schedule 02.08.2019The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand.
Это подразумевает для меня, чтоa[0] << 8
не теряет биты, а вместо этого повышается до чего-то большего. Здесь мне нужен языковой юрист для перевода, но быстрый тест компиляции показывает, что это так. Но это может быть неопределенное поведение, соответствующее обычной реализации. Кто-нибудь, помогите мне здесь. - person selbie   schedule 02.08.2019uint8_t
? Как это согласуется с сообщением Clang-Tidy, упомянутым в комментариях? - person JaMiT   schedule 02.08.2019static_cast()
? - person   schedule 02.08.2019a[0] >= 128
? Отрицательное число? - person L. F.   schedule 02.08.2019a[0] * 256 + a[1]
работает так же хорошо и генерирует идентичный исполняемый код с современными компиляторами. - person n. 1.8e9-where's-my-share m.   schedule 02.08.2019