繁体   English   中英

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”从基本类型有符号 32 位 int 到不同或更窄基本类型无符号 8 位 int 的隐式转换。

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

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

还有什么是解决这个问题的正确方法?

这是由于整数促销而发生的。 这在C 标准的第 6.3.1.1 节中有详细说明

2可以在可以使用intunsigned int的表达式中使用以下内容:

  • 具有整数类型(除了intunsigned int )的对象或表达式,其整数转换等级小于或等于in t 和unsigned int的等级。
  • _Boolintsigned intunsigned int类型的位域。

如果int可以表示原始类型的所有值(受宽度限制,对于位域),则该值将转换为int 否则,它被转换为unsigned int 这些被称为整数提升。 整数提升不会改变所有其他类型。

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

uint8_t var6 = var4 + var5;

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

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

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

原因是隐式类型促销 在那一行中有3个隐含的促销,这是危险和草率的风格。 您可以在一行代码中同时进行整数提升/通常的算术转换和隐式左值转换。

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

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

执行通常算术转换的运算符的两个操作数应具有相同的基本类型类别。

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位操作数的表达,因为编译器可以自由地优化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM