Использование малого целого числа с оператором бит в C

В связи с предыдущим вопросом я не могу понять некоторые правила MISRA C 2004.

В ISO C99 draft 2007, в разделе 6.5 §4:

Некоторые операторы (унарный оператор ~ и бинарные операторы <, → , &, ^ и |, совместно описываемые как побитовые операторы), должны иметь операнды, которые имеют целочисленный тип. Эти операторы дают значения, которые зависят от внутренних представлений целых чисел, и имеют определенные для реализации и undefined аспекты для подписанных типов.

Хорошо, используя знаковое целое с побитовыми операторами, может создавать поведение undefined (и не имеет смысла).

Хорошим решением является использование явного преобразования в более широкий беззнаковый целочисленный тип для обхода интегральной рассылки, а затем не использовать знаковое значение с побитовыми операторами (см. связанные ответы моего предыдущего вопроса).

Но в MISRA C 2004 возможно использование небольших целых без знака с побитовыми операторами (например, правило 10.5). Почему, если интегральное продвижение приводит к использованию подписанных значений с побитовыми операторами? Я думаю, что я не понимаю некоторых вещей.

Ответ 1

Правила не противоречат друг другу, и вам не нужно расширять тип. Вы можете сразу же вернуть результат двоичной операции с небольшим двоичным кодом обратно в свой тип.

Маленькое целое число не будет повышаться до int для сдвигов, если первый операнд не является int.

Это из их примера:

uint8_t port = 0x5aU;
uint8_t result_8;
uint16_t result_16;

result_8 = (~port) >> 4;  /* not compliant */
result_8 = ((uint8_t)(~port)) >> 4; /* compliant */
result_16 = ((uint16_t)(~(uint16_t)port)) >> 4; /* compliant */