Второй вопрос первый:
Как мне сделать код, совместимый с MISRA C: 2004?
Вы можете написать это в соответствии с MISRA следующим образом:
typedef unsigned int UNS_32;
UNS_32 test(void);
UNS_32 test(void)
{
UNS_32 original_arg = 3U;
UNS_32 irq_source = 1UL << original_arg;
return irq_source;
}
Вернуться к первому вопросу:
Что здесь на самом деле происходит?
Первое правило 10.3 гласит, что сложные целочисленные выражения не должны приводиться к типу, более широкому, чем базовый тип.
Одним из ключей к пониманию сообщения об ошибке является концепция базового типа , которая является специфической концепцией MISRA-C. Короче говоря, базовый тип константы - это самый маленький тип, в который она может вписаться В этом случае 1U
имеет базовый тип unsigned char
, несмотря на то, что он имеет тип языка unsigned int
.
Логическое обоснование правила 10.3 состоит в том, чтобы избежать случаев, когда результат операции используется в контексте, который больше, чем части. Стандартным примером этого является умножение, где alpha
и beta
являются 16-битными типами:
uint32_t res = alpha * beta;
Здесь, если int
равен 16 битам, умножение будет выполняться в 16 битах, а результат будет преобразован в 32 бита. С другой стороны, если int
равен 32 битам или больше, умножение будет выполняться с большей точностью. Конкретно, это будет отличать результат при умножении, скажем, на 0x4000 и 0x10.
Правило 10.3 MISRA решило эту проблему, установив, что результат приведения помещается во временный тип, который затем приводится к более крупному типу. Таким образом, вы вынуждены так или иначе писать код.
Если предполагается использовать 16-битное умножение:
uint16_t tmp = alpha * beta;
uint32_t res = tmp;
С другой стороны, если целью является 32-битное умножение:
UNS_32 res = (UNS_32)alpha * (UNS_32)beta;
Итак, в этом случае выражение 1U << count
является потенциальной проблемой. Если converted_arg
больше 16 бит, это может привести к проблеме при использовании 16-битных int
с. Однако MISRA позволяет вам писать 1UL << count
или (UNS_32)((UNS_32)1U << original_arg)
. Вы упомянули, что в последнем случае средство проверки MISRA выдало ошибку - у меня ее нет, поэтому повторите проверку.
Итак, на мой взгляд, средство проверки MISRA C, которое вы использовали правильно, выявило нарушение правила 10.3.