Основная проблема здесь не имеет ничего общего с MISRA, но с попыткой сохранить значение в указанном c слоте в битовом поле. Вы не можете знать, как ваша схема расположения битовых полей в действительности оказывается в памяти, потому что это не определено в стандарте C.
Ваше битовое поле выделяет 8 битов значения в байте MS или байте LS? Это соответствует порядку байтов или нет? Что такое битовый порядок? Никто не знает. Шаг 1 - избавиться от битового поля.
Шаг 2 - избавиться от чего-либо unsigned int
и использовать uint16_t
/ uint32_t
.
Что касается В частности, MISRA- C 10.6, правило против неявного преобразования в более широкий тип всегда было ошибочным. Логическое обоснование MISRA, использованное для этого правила, заключалось в том, чтобы запретить людям писать код, подобный uint32_t u32 = u16a + u16b;
, и думать, что операнд u32
, равный =
, каким-то волшебным образом означает, что операция будет выполняться на 32 битах вместо 16. Но на 8/16 битная система, она выполняется с 16-битной арифметикой c и могут быть переполнения / обходы.
Теперь, как это происходит, выполнение битовых сдвигов на знаковых типах всегда очень плохая идея. pData[0]
получает неявное повышение до int
, которое подписано. Есть и другие правила MISRA, а не те, которые вы цитировали.
Независимо от MISRA, вы должны всегда иметь привычку выполнять смены на неподписанных типах. «Это не опасно в этом случае» - унылое обоснование. Это означает, что всегда пишите (uint32_t)pData[0] >> 5
, а приведение должно применяться до , а не после него. Это устраняет все неопределенности относительно неопределенного поведения левых сдвигов и потенциально арифметических c правых сдвигов и c. Пусть оптимизатор будет беспокоиться о фактическом используемом размере операндов оттуда.