我的静态分析仪发出以下警告:
MCPP规则5-0-3:此复杂表达式隐式转换为a 不同的基本类型
代码如下:
void func(const uint32_t arg)
{
//32U has underlying type uint8_t
const uint32_t u32a = arg % 32U; //warning issued in this line
const uint32_t u32b = (arg % static_cast<uint32_t>(32U)); //same warning issued in this line
const uint32_t u32c = static_cast<uint32_t>(arg % 32U); //compliant
}
根据MISRA基础类型转换规则:
否则,如果两个操作数都具有整数类型,则为基础类型 表达式可以使用以下方法找到:
- 如果是的类型 操作数大小相同,或者是无符号的,结果是 无符号。
- 否则,结果的类型是较大的类型 类型。
我认为此警告可能是误报,因为尽管32U
为uint8_t
,但表达式应采用较大类型的基础类型,在本例中为uint32_t
因此需要static_cast
不必要。
你是否同意这是误报?或者我看错了吗?
编辑: MISRA标准规定:
因此,整数常量表达式的基础类型 定义如下:
如果表达式的实际类型是有符号整数,则基础类型被定义为最小的有符号整数类型 能够代表其价值。
如果表达式的实际类型是无符号整数,则基础类型定义为最小无符号整数类型 能够代表其价值。
- 醇>
在所有其他情况下,表达式的基础类型定义为与其实际类型相同。
没有。 2是我假设32U
具有基础类型uint8_t
的原因。
答案 0 :(得分:2)
我认为这个警告可能是误报,因为尽管
32U
是uint8_t
32U
在任何平台上都不是uint8_t
。对于整数文字,您可以表达的最小类型是int
/ unsigned int
。 According to cppreference nnnnU
可以
unsigned int
,unsigned long int
或unsigned long long int
。32U
。它确实选择了可以存储文字的第一种类型,因此unsigned int
是32U
。
因此,如果您想保证uint32_t
与new SimpleDateFormat("EE").format(date);
的类型相同,那么您需要在右侧进行演员表。
答案 1 :(得分:2)
32U
的类型为unsigned
,可能与uint32_t
的类型不同。与您的陈述相反,它永远不属于uint8_t
unsigned
仅保证能够代表0
到65535
范围内的值,但允许支持更大的范围。它实际上可以代表的是实现定义。但是,它不能是uint8_t
,因为uint8_t
无法表示unsigned
所需的范围。
这实际上意味着,unsigned
可能是16位类型,32位类型甚至64位类型的三种可能性 - 它们分别是更小,相同的大小,或大于uint32_t
。
表达式arg % 32U
的结果可能是uint32_t
类型(如果unsigned
是16位),uint32_t
(如果unsigned
和{ {1}}都是相同的32位类型),或uint32_t
(如果unsigned
是64位类型)。在最后一种情况下,需要从unsigned
转换为unsigned
才能初始化uint32_t
。
您的静态分析仪警告您系统之间行为的这种潜在变化。
所以,不,这不是假阳性。
答案 2 :(得分:1)
您已找到相关部分。文字所在表达式的类型是无符号的,因此基础类型是可以适合无符号值uint8_t
的最小值,意思是32
。如果文字是uint32_t arg; ... arg % 32U
没有U后缀(虽然这会违反其他MISRA规则),它将具有相同的基础类型。
MISRA的目标是在特定表达式uint32_t
中永远不会发生危险的隐式转换。话虽这么说,你可以安全地将文字投射到arg % static_cast<uint32_t>(32U)
,这应该使所有警告都沉默。无论MISRA说什么/不说什么,确保代码中没有隐式类型促销是好的编程实践。
如果静态分析器的目的只是检查一般的隐式促销,那么警告就可以了。如果您的静态分析仪的目的是检查MISRA合规性,那么这是误报。
无论工具的用途如何,行lib
都不应产生任何形式的诊断。这当然是一种误报。