那条线是一个难以理解的混乱。考虑将其拆分以增加可读性。根据系统上 int 的宽度,代码看起来会有所不同。下面的代码假定为 32 位整数。
uint8_t bit = (uint8_t)( ((uint32_t)intNumber + 1U) & 0x1U );
uint32_t lShift32 = ((uint32_t)bit << ADC_INTSELxNy_LOG2_NUMBITS_PER_REG);
uint_least8_t lShift8 = (uint_least8_t)((uint32_t)ADC_INTSELxNy_NUMBITS_PER_REG - lShift);
现在至于出现错误的原因,规则 10.1 和 10.3 与隐式整数类型提升有关。如果您像我在上面所做的那样拆分代码,您将不会对每个子表达式的“基础类型”感到困惑。您做错的是在操作之前向基础类型添加强制转换,这没有什么好处。您需要在每次操作后执行此操作。
+ 操作需要在+ 操作之后显式转换为基础类型,与 & 操作和 shift 操作相同。最后仅将所有内容都转换为底层类型是不够的,您必须单独考虑每个子表达式。
解释我上面的代码:
第一行有一个显式转换uint32_t
以确保它intNumber
与1U
. 这样,就没有子表达式的隐式转换,intNumber + 1U
这是与基础类型 uint8_t 具有相同符号的更广泛类型(意味着它是安全的)。加法的结果是 unsigned int 类型。同样,unsigned int & unsigned int
不会产生隐式转换。最后将结果转换为 uint8_t 以满足许多 MISRA 规则。其余代码以相同的方式进行。
我总是尝试在操作之前将扩展转换为大整数类型,以简化所有内容,避免隐式提升并避免相互之间进行大量转换。
请注意,规则 10.1 的真正目的实际上是强迫您了解 C 中的隐式类型提升。这是一个相当复杂的话题,但数量惊人的 C 程序员却忽略了类型提升以及由他们。更多关于类型提升规则的信息在这里。