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 in
t 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_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 个隐式提升,这是危险和草率的风格。您在一行代码中同时进行了整数 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 位操作数的表达式相比,它不会影响性能,因为编译器可以自由优化。
我收到 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
orunsigned int
may be used:
- An object or expression with an integer type (other than
int
orunsigned int
) whose integer conversion rank is less than or equal to the rank ofin
t andunsigned int
.- A bit-field of type
_Bool
,int
,signed int
, orunsigned 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 anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions. All other types are unchanged by the integer promotions.
因为 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);
原因是
您必须了解这些覆盖在 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 位操作数的表达式相比,它不会影响性能,因为编译器可以自由优化。