给定变量a
、b
和c
:
uint32_t a;
uint16_t b, c;
根据 MISRA-C 2012 标准,表达式a+b+c
是合规的,而b+c+a
不是不合规的。
为什么?
由于 C 允许自动执行不同算术类型之间的赋值,因此使用这些隐式转换可能会导致意外结果,可能会丢失值、符号或精度。MISRA_C:2012 通过其“基本类型”模型强制执行强类型,以帮助在可能发生这种情况时发出警告 - 称为 10.x 规则。
在这种情况下,存在溢出损失的可能性u16a+u16b+u32c
具体来说,这是违反 MISRA C:2012 Rule-10.7:“如果复合表达式用作执行通常算术转换的运算符的一个操作数,则另一个操作数不应具有更广泛的基本类型”。
假设评估受到更广泛类型的影响,这是一个常见的错误。表达式的类型实际上是由它的操作数在任何整数提升后的类型决定的。您可以通过强制转换为更宽的类型来解决此问题,或者重新排列表达式开头的操作数,如您在第一个示例中所示:u32a+u16b+u16c
注意:这并不意味着表达式中的所有操作数都具有相同的基本类型。表达式 u32a + u16b + u16c 是兼容的,因为这两个加法理论上都将在 uint32_t 类型中执行。
使用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