Система типа C одновременно тонкая и опасная. Явное преобразование может быть необходимым, а может и не быть. В частности, в случае (uint16_t) nbr & 0x0000FFFF
приведение не является правильным, предполагая 32-битный процессор.
Вы произносите перед операцией. Это означает, что операнд nbr
будет явно преобразован путем приведения, а затем немедленно неявно преобразован до int
путем неявного целочисленного преобразования. Результат будет иметь тип int
, который является подписанным. Безвреден в этом случае, но может вызвать проблемы в других случаях. Используя неправильный состав, вы сделали signed int
из uint32_t
, что не было целью.
В целом вам необходимо знать правила продвижения неявного типа.
Хотя существует неявное преобразование lvalue при присвоении обратно uint16_t
, что в большинстве случаев спасает положение.
Также обратите внимание, что 0x0000FFFF
— опасный стиль. Шестнадцатеричные литералы относятся к типу, в котором значение будет соответствовать, независимо от того, сколько нулей вы поставили перед значением. В данном случае это int
, который подписан. В 16-битной системе 0x0000FFFF
даст int
, а 0x00008000
даст unsigned int
. (Проверьте, например, эту странную ошибку: Почему 0 ‹ -0x80000000?)
Лучшей практикой, надежным, переносимым, совместимым с MISRA-C кодом является код, который вообще не содержит никаких неявных преобразований:
uint32_t nbr = ...;
uint16_t lower_word = (uint16_t) (nbr & 0xFFFFUL);
uint16_t upper_word = (uint16_t) ((nbr >> 16) & 0xFFFFUL);
Это предполагает, что nbr
известно как uint32_t
, в противном случае рекомендуется привести этот операнд к uint32_t
перед приведением.
В данном конкретном случае маски на самом деле не нужны, но в общем случае, например, при маскировании 4 байтов из uint32_t
.
person
Lundin
schedule
21.12.2018