我正在获得Misra C-2012规则10.3违规:从必需类型签名的32位INT到不同或较窄的必需类型的Unsigned 8位INT"的" VAR4 VAR5"的隐式转换"对于以下代码。
int8_t var4 = -10;
uint8_t var5 = 15;
uint8_t var6 = var4 + var5;
如何解释" var4 var5" aa 32 int,因为每个int是8位大小。
以及解决此问题的正确方法是什么?
这是由于整数促销而发生的。这在C标准的第6.3.1.1节
的第6.3.1.1节中进行了详细说明。2 可以在表达式中使用以下任何
int
或unsigned int
的表达式中使用:
- 具有整数类型的对象或表达式(
int
或unsigned int
除外),其整数转换等级小于或等于in
T和unsigned int
的等级。- 类型
_Bool
,int
,signed int
或unsigned int
。如果
int
可以表示原始类型的所有值(如限制 在宽度上,对于一个位场),该值转换为int
; 否则,将其转换为unsigned int
。这些称为 整数促销。所有其他类型都没有整数不变 促销。
由于int8_t
和uint8_t
的等级低于int
,因此在表达式中使用时,这些类型的变量将促进到int
。如果是:
uint8_t var6 = var4 + var5;
var4
和var5
均升级为int
,+
操作员的结果也为int
类型。然后将该值分配回var6
,即uint8_t
,这可能导致值的截断。
最好的处理方法是首先验证结果无法溢出,然后明确施放结果:
uint8_t var6 = (uint8_t)(var4 + var5);
隐式类型促销的原因。在那条线上有3个隐性促销,这是危险和草率的风格。您既有整数促销/通常的算术转换,也具有单一代码行中的隐式lvalue转换。
您必须了解这些覆盖物在C中的工作方式,以编写免费的C代码,但是您还必须理解它们才能使用Misra-C。实际上,Misra-C的目的之一一直是教育程序员有关隐式类型促销活动 - 您还会在Misra-C文档中找到解释。
您的代码实际上违反了几个Misra-C:2012规则。不仅关注隐式lvalue转换的10.3,而且还关注10.4:
执行通常的算术转换的操作员的两个操作数应具有相同的必需类型类别。
var4
基本上是签名,var5
本质上是未签名的。因此,仅将结果投入到适当的类型是不够的。要获取Misra-C符合代码,您必须将这两个操作数施加到同一类型。或者更好的是,使用适当类型的变量首先:将-10 + 15
的结果存储在无符号变量中是没有意义的。您要么需要签名的数字,要么不需要。
要获取也完全便携式的MISRA-C符合MISRA-C的代码,这应该是一种无法隐式推广的类型,例如uint32_t
。
uint8_t var6 = (uint8_t) ((uint32_t)var4 + (uint32_t)var5);
替代
int8_t var6 = (int8_t) ((int32_t)var4 + (int32_t)var5);
这种表达式是坚固的,专业的C,因为它不包含单个隐式促销。它是自我文献的代码,因为它表明程序员知道并考虑了隐式类型的促销。与仅具有8位操作数的表达式相比,它确实会影响性能,因为编译器可以免费优化。