MISRA警告<复杂的表达式被隐式转换为不同的基本类型。

时间:2019-07-11 07:13:33

标签: c++ misra

MISRA C ++规则:5_0_3

尝试使用一种符合MISRA的静态工具分析器,无法解决它。

#include<iostream>
#include<stdlib.h>

using namespace std;

int main()
{
    uint32_t num = 0U;
    bool Flag =false;

    num |= (Flag ? (0b10 << 10):(0b00 << 10));
}

请帮助解决此问题。 错误消息是: 1.此二进制按位运算符的非常数操作数具有不同的基本类型。 2.这个复杂的表达式被隐式转换为另一个基本类型。

1 个答案:

答案 0 :(得分:1)

首先,0b语法是非标准的,因此无法确定它将做什么。仅该语法就违反了MISRA;我建议改用十六进制常量。无论如何,您的代码不应包含任何“魔术数字”。

如果我们假设您的编译器将非标准0b整数常量视为常规十进制整数常量,则其类型为(带符号)int。您的操作结果是带符号的int,即MISRA称之为“基本上带符号”。但是,您将其存储在uin32_t中,该变量实际上是未签名的,这是MISRA违规行为和错误的原因。

请注意,移位运算符始终具有提升的左操作数整数的类型。因此,编写类似0b10 << 10u的内容将无济于事。根据经验,从不在带符号的操作数上不使用按位运算符。

还要注意,?:是特殊的,因为它包含第二和第三操作数的隐式转换-它们被平衡为相同的类型(根据“通常的算术转换”)。这会产生一些细微的错误,因此,在使用小整数类型或带符号类型(或在使用MISRA的情况下)时,最好不要使用?:

我还建议将代码重写为“魔术数字”较少的内容:

#define MASK_SOMETHING  (0x2u << 10) // give this some meaningful name
#define MASK_EMPTY      (0x0u << 10) // give this some meaningful name

uint32_t num = 0U;
bool Flag = false;

...

if(Flag)
{
  num |= MASK_SOMETHING;
}

显然,对零进行按位或运算不是很有意义,如果没有设置标志,您可能打算清除位?在这种情况下,您需要else { num &= ~MASK_EMPTY; }

(也可以进一步优化以摆脱分支。)