MISRA C++ 规则 5-0-3 误报警告
MISRA C++ rule 5-0-3 false positive warning
我的静态分析器发出以下警告:
MCPP Rule 5-0-3: This complex expression is implicitly converted to a
different essential type
对于以下代码:
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底层类型转换规则:
Otherwise, if both operands have integral type, the underlying type of
the expression can be found using the following:
– If the types of the
operands are the same size, and either is unsigned, the result is
unsigned.
– Otherwise, the type of the result is that of the larger
type.
我认为这个警告可能是误报,因为尽管 32U
是 uint8_t
,表达式应该采用较大类型的基础类型,在本例中是 uint32_t
,因此不需要 static_cast
。
你同意这是误报吗?还是我看错了?
编辑:
MISRA 标准规定:
The underlying type of an integer constant expression is therefore
defined as follows:
If the actual type of the expression is signed integral, the underlying type is defined as the smallest signed integer type that is
capable of representing its value.
If the actual type of the expression is unsigned integral, the underlying type is defined as the smallest unsigned integer type that
is capable of representing its value.
In all other circumstances, the underlying type of the expression is defined as being the same as its actual type.
没有。 2 是我必须假设 32U
具有 uint8_t
.
基础类型的原因
I think this warning may be a false positive because, despite the 32U
being a 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
的类型相同,那么你需要在右侧进行强制转换。
32U
是 unsigned
类型,这可能是与 uint32_t
不同的类型。与您的陈述相反,它永远不是 uint8_t
类型
A unsigned
只保证能够表示 0
到 65535
范围内的值,尽管允许支持更大的范围。它实际可以表示的是实现定义的。但是,它不能是 uint8_t
,因为 uint8_t
不能表示 unsigned
.
所需的范围
这意味着,实际上,三种可能性是 unsigned
可能是 16 位类型、32 位类型,甚至是 64 位类型——它们分别更小,相同大小,或大于 uint32_t
.
表达式 arg % 32U
的结果因此可能是 uint32_t
类型(如果 unsigned
是 16 位),uint32_t
(如果 unsigned
和 uint32_t
都是相同的 32 位类型),或者 unsigned
(如果 unsigned
是 64 位类型)。在最后一种情况下,需要从 unsigned
到 uint32_t
的转换来初始化 u32a
。
您的静态分析器警告您注意系统之间的这种潜在行为差异。
所以,不,这不是误报。
您已找到相关部分。字面量所在表达式的类型是无符号的,所以底层类型是最小的可以容纳无符号值32
的类型,即uint8_t
。如果文字 32
没有 U 后缀,它将具有完全相同的基础类型(尽管这会违反其他 MISRA 规则)。
MISRA 的目标是在特定表达式 uint32_t arg; ... arg % 32U
中永远不会发生危险的隐式转换。话虽如此,您可以安全地将文字转换为 uint32_t
并且这应该会消除所有警告。无论 MISRA says/doesn 怎么说,确保代码中没有任何隐式类型提升是良好的编程习惯。
如果静态分析器的目的只是一般检查隐式提升,那么警告是可以的。如果您的静态分析器的目的是检查 MISRA 合规性,那么它就是误报。
行 arg % static_cast<uint32_t>(32U)
永远不会产生任何形式的诊断,无论该工具的用途如何。那肯定是误报。
我的静态分析器发出以下警告:
MCPP Rule 5-0-3: This complex expression is implicitly converted to a different essential type
对于以下代码:
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底层类型转换规则:
Otherwise, if both operands have integral type, the underlying type of the expression can be found using the following:
– If the types of the operands are the same size, and either is unsigned, the result is unsigned.
– Otherwise, the type of the result is that of the larger type.
我认为这个警告可能是误报,因为尽管 32U
是 uint8_t
,表达式应该采用较大类型的基础类型,在本例中是 uint32_t
,因此不需要 static_cast
。
你同意这是误报吗?还是我看错了?
编辑: MISRA 标准规定:
The underlying type of an integer constant expression is therefore defined as follows:
If the actual type of the expression is signed integral, the underlying type is defined as the smallest signed integer type that is capable of representing its value.
If the actual type of the expression is unsigned integral, the underlying type is defined as the smallest unsigned integer type that is capable of representing its value.
In all other circumstances, the underlying type of the expression is defined as being the same as its actual type.
没有。 2 是我必须假设 32U
具有 uint8_t
.
I think this warning may be a false positive because, despite the
32U
being auint8_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
的类型相同,那么你需要在右侧进行强制转换。
32U
是 unsigned
类型,这可能是与 uint32_t
不同的类型。与您的陈述相反,它永远不是 uint8_t
A unsigned
只保证能够表示 0
到 65535
范围内的值,尽管允许支持更大的范围。它实际可以表示的是实现定义的。但是,它不能是 uint8_t
,因为 uint8_t
不能表示 unsigned
.
这意味着,实际上,三种可能性是 unsigned
可能是 16 位类型、32 位类型,甚至是 64 位类型——它们分别更小,相同大小,或大于 uint32_t
.
表达式 arg % 32U
的结果因此可能是 uint32_t
类型(如果 unsigned
是 16 位),uint32_t
(如果 unsigned
和 uint32_t
都是相同的 32 位类型),或者 unsigned
(如果 unsigned
是 64 位类型)。在最后一种情况下,需要从 unsigned
到 uint32_t
的转换来初始化 u32a
。
您的静态分析器警告您注意系统之间的这种潜在行为差异。
所以,不,这不是误报。
您已找到相关部分。字面量所在表达式的类型是无符号的,所以底层类型是最小的可以容纳无符号值32
的类型,即uint8_t
。如果文字 32
没有 U 后缀,它将具有完全相同的基础类型(尽管这会违反其他 MISRA 规则)。
MISRA 的目标是在特定表达式 uint32_t arg; ... arg % 32U
中永远不会发生危险的隐式转换。话虽如此,您可以安全地将文字转换为 uint32_t
并且这应该会消除所有警告。无论 MISRA says/doesn 怎么说,确保代码中没有任何隐式类型提升是良好的编程习惯。
如果静态分析器的目的只是一般检查隐式提升,那么警告是可以的。如果您的静态分析器的目的是检查 MISRA 合规性,那么它就是误报。
行 arg % static_cast<uint32_t>(32U)
永远不会产生任何形式的诊断,无论该工具的用途如何。那肯定是误报。