MISRA C-2012 违反规则 10.3 由于添加两个 8 位变量导致 32 位

MISRA C-2012 Rule 10.3 violation due to adding of two 8 bit variables which resulted in 32 bit

我收到 MISRA C-2012 规则 10.3 违规:"var4 + var5" 从基本类型 signed 32 位 int 到不同或更窄的基本类型 unsigned 8-bit int 的隐式转换“对于以下代码。

int8_t var4 = -10;
uint8_t var5 = 15;
uint8_t var6 = var4 + var5;

如何将 "var4 + var5" 解释为 32 位 int,因为每个都是 8 位大小。

以及解决此问题的正确方法是什么?

发生这种情况是由于 整数提升C standard

的第 6.3.1.1 节对此进行了详细说明

2 The following may be used in an expression wherever an int or unsigned int may be used:

  • An object or expression with an integer type (other than int or unsigned int) whose integer conversion rank is less than or equal to the rank of int and unsigned int.
  • A bit-field of type _Bool, int, signed int, or unsigned int.

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.

因为 int8_tuint8_t 的等级低于 int,所以这些类型的变量在表达式中使用时会提升为 int。在以下情况下:

uint8_t var6 = var4 + var5;

var4var5都提升为int+运算符的结果也是int类型。然后将该值分配回 var6,这是一个 uint8_t,这可能会导致该值被截断。

处理此问题的最佳方法是首先验证结果不会溢出,然后显式转换结果:

uint8_t var6 = (uint8_t)(var4 + var5);

原因是。单行中有 3 个隐式提升,这是危险和草率的风格。您在一行代码中同时进行了整数 promotion/usual 算术转换和隐式左值转换。

您必须了解这些覆盖在 C 中的工作方式,才能编写无错误的 C 代码,但您还必须了解它们才能使用 MISRA-C。事实上,MISRA-C 的目的之一一直是让程序员了解隐式类型提升 - 您还可以在 MISRA-C 文档中找到解释。

您的代码实际上违反了多项 MISRA-C:2012 规则。不仅 10.3 关注隐式左值转换,而且 10.4:

Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category.

var4 本质上是有符号的,var5 本质上是无符号的。因此,仅仅将结果转换为适当的类型是不够的。要获得符合 MISRA-C 的代码,您必须将两个操作数转换为相同的类型。或者更好的做法是,首先使用适当类型的变量:将 -10 + 15 的结果存储在无符号变量中没有多大意义。您要么需要签名号码,要么不需要。

要获得完全可移植的符合 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 位操作数的表达式相比,它不会影响性能,因为编译器可以自由优化。