Соответствие MISRA C для арифметического сложения
Учитывая переменные a
, b
, а также c
:
uint32_t a;
uint16_t b, c;
Согласно стандарту MISRA-C 2012, выражение a+b+c
соответствует в то время как b+c+a
не соответствует.
Зачем?
2 ответа
С u16a+u16b+u32c
, u16a+u16b
является unsigned
(думаю, 16-битное) дополнение с потенциальным переполнением, потерянным до последующего добавления к u32c
,
u32a+u16b+u16c
добавляет u32a+u16b
а затем использует этот 32-битный результат при добавлении 16c
предотвращая эту потерю.
пример
0x8000 + 0x8000 + 0x10000
(0x8000 + 0x8000) + 0x10000
0 + 0x10000
0x10000
против
0x10000 + 0x8000 + 0x8000
(0x10000 + 0x8000) + 0x8000
0x18000 + 0x8000
0x20000
Поскольку C позволяет автоматически выполнять присваивания между различными арифметическими типами, использование этих неявных преобразований может привести к непредвиденным результатам с потерей значения, знака или точности. MISRA_C:2012 обеспечивает строгую типизацию с помощью своей модели "существенного типа", чтобы предупредить, когда это может произойти - так называемые правила 10.x.
В этом случае существует вероятность потери переполнения с u16a+u16b+u32c
В частности, это нарушение MISRA C:2012 Правило-10.7: "Если составное выражение используется в качестве одного операнда оператора, в котором выполняются обычные арифметические преобразования, тогда другой операнд не должен иметь более широкого существенного типа".
Распространенная ошибка - предполагать, что на оценку влияет более широкий тип. Тип выражения фактически определяется типом его операндов после любого интегрального продвижения. Вы можете исправить это, приведя к более широкому типу, или переставить операнды в начале выражения, как показано в первом примере: u32a+u16b+u16c
Примечание: это не означает, что все операнды в выражении имеют одинаковый существенный тип. Выражение u32a + u16b + u16c является совместимым, поскольку оба добавления будут условно выполняться в типе uint32_t.