2017-04-04 54 views
4

我的静态分析器是投掷以下警告:MISRA C++规则5-0-3假阳性警告

MCPP规则5-0-3:该复合物的表达隐式转换为 不同必不可少类型

为以下代码:

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标准指出:

基础类型的整数常量表达式的因此是 定义如下:

  1. 如果表达式的实际类型是有符号的积分,底层类型被定义为 能够表示其值的最小有符号整数类型。

  2. 如果表达式的实际类型是无符号整数,基础类型被定义为最小无符号整数类型 是能够代表其值的。

  3. 在所有其他情况下,表达式的基础类型被定义为与其实际类型相同。

2号就是为什么我一直假设32U具有基础类型的uint8_t的原因。

+0

在你的架构,'32U'可能是64位。你为什么说“_32U有基础类型uint8_t_”? – YSC

+1

如果你的int是比'uint32_t'越大,则'ARG%32U'是类型'无符号int'而不是'uint32_t'的。 – Jarod42

+0

要检查,只是'的std ::法院<<的sizeof(unsigned int类型)<< “\ n”;'。 – YSC

回答

1

您已找到相关部分。文字所在表达式的类型是无符号的,所以基础类型是可以适合无符号值32,即uint8_t的最小的一个。如果没有U后缀的文字是32(尽管这会违反其他MISRA规则),它将具有相同的基础类型。

MISRA的目标是在特定表达式uint32_t arg; ... arg % 32U中永远不会发生危险的隐式转换。话虽如此,你可以安全地将文字转换成uint32_t,并且应该使所有警告消失。无论MISRA说/不说什么,确保代码中不存在隐式类型促销活动,这是很好的编程实践。

如果静态分析器的目的通常是检查隐式升级,那么警告就没有问题。如果您的静态分析仪的目的是检查MISRA合规性,那么这是一个误报。

线arg % static_cast<uint32_t>(32U)从不应该产生任何形式的诊断,而不管该工具的目的。这当然是一个误报。

2

我认为这个警告可能是假阳性,因为,尽管32U是一个uint8_t

32U没有任何平台上uint8_t。对于整数文字,您可以表达的最小类型是int/unsigned intAccording to cppreferencennnnU可以是 a unsigned int,unsigned long intunsigned long long int。它确实选择了第一种可存储文字的类型,所以32Uunsigned int

所以,如果你想保证32U是与uint32_t相同的类型,那么你需要在右侧的演员阵容。

+0

我刚刚修改后 – mikearmagedon

+0

@mikearmagedon我不熟悉MISRA这样我就可以知道B一定的,但我认为在谈论刚刚'32'。正如你在编译时所知道的那样,'32'可以被视为一个有效的'uint8_t'。用32U,尽管你告诉编译器你希望它是一个带'U'的'unsigned int'。 – NathanOliver

+0

@NathanOliver。字面值'32'是'int'类型。 – Peter

2

32Uunsigned类型,它可能是与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(如果unsigneduint32_t都是相同的32位类型),或unsigned(如果unsigned是一个64位类型)。在最后一种情况下,需要将unsigned转换为uint32_t以初始化u32a

您的静态分析器警告您系统之间行为的这种潜在变化。

所以,不,这不是假阳性。

+0

的问题是关于MISRA-C++ 2008的基础类型的概念,所以这并不能回答这个问题。 – Lundin