Соответствие 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.

Другие вопросы по тегам