Поразрядный сдвиг (varUint8 ›› 7) & 0x01u - соответствует требованиям Misra

Я устраняю какой-то код, и я обнаружил эту строку

uint8var = ((constUint8[0]) >> 7) & 0x01u;

Мне было интересно, какова в этом правильная практика. Требуется ли & 0x01u для правильной реализации при написании кода, совместимого с MISRA, учитывая, что я сдвигаю uint8 на 7 цифр вправо?


person user145760    schedule 12.04.2019    source источник
comment
Я не понимаю, что вас беспокоит. Вы можете уточнить?   -  person John Bollinger    schedule 12.04.2019
comment
Я не знаю, правильная ли это практика, хотя & 1 было бы гораздо более читаемым IMO, а если constUint8[0] 8 бит, вся операция избыточна.   -  person joH1    schedule 12.04.2019
comment
Мой компилятор превращает (x >> 7) & 0x01, x >> 7 и !!(x & 0x80) (где x - беззнаковый символ) в одну и ту же инструкцию ... если есть сомнения, проверьте сборку.   -  person Shawn    schedule 12.04.2019
comment
@Shawn: Проверка кода сборки не дает ответа на вопрос, соответствует ли этот код правилам MISRA. MISRA заботится о том, будет ли исходный код давать желаемые результаты во всех применимых реализациях C. Тот факт, что одна реализация дает желаемый результат в одной ситуации, не демонстрирует желаемого свойства.   -  person Eric Postpischil    schedule 12.04.2019
comment
Какие типы переменных uint8_t?   -  person Lundin    schedule 12.04.2019


Ответы (1)


Сдвиг вправо uint8_t никогда не может быть проблемой сам по себе. Однако цель MISRA-C - запретить вам писать ошибки, вызванные неявным целочисленным продвижением. В вашем случае constUint8[0] будет неявно повышен до подписанного int. Это вызовет различные проблемы соответствия MISRA, которых легче всего избежать, если в первую очередь убедиться, что ваш код не содержит неявных рекламных акций.

Когда дело доходит до сдвигов, это означает приведение к большому целочисленному типу перед сдвигом:
(uint32_t)constUint8[0] >> 7.

Маска с 0x01u лишняя и не добавляет значения. Его можно безопасно удалить. Чтобы добиться соответствия MISRA-C, лучше всего переписать код следующим образом:

uint8var = (uint8_t) ((uint32_t)constUint8[0] >> 7);

где приведение (uint8_t) гарантирует, что неявное преобразование отсутствует, но мы явно вернемся к намеченному типу. MISRA-C не допускает неявного присвоения более крупных типов более мелким.

Для получения дополнительной информации см. правила продвижения неявного типа.

person Lundin    schedule 12.04.2019
comment
Почему MISRA-C принимает приведение к uint32_t как достаточное, чтобы избежать повышения до целого числа со знаком? Мне любопытно, какие предположения он делает или в каких условиях ограничивает себя. - person Eric Postpischil; 12.04.2019
comment
@EricPostpischil Это не так, я просто предполагаю, что это реальный компьютер, где int либо 16, либо 32 бит. - person Lundin; 14.04.2019