在分析以下代码时出现以下MISRA违规行为:
#define z (USHORT)14745
#define Convert(x) ((((USHORT)x*(unsigned short)1000) + ((z) / (USHORT)2)) /(z))
static const USHORT array [2] =
{
Convert(176), -> Line "1"
Convert(206) -> Line "2"
};
在“1”,“2”两行上检测到以下MISRA违规:
积分提升:unsigned short提升为unsigned int。 参考 - ISO:C90-6.2.1.1字符和整数
常量:无符号算术运算中的环绕声。 MISRA-C:2004规则12.11;参考 - ISO:C90-6.1.2.5类型
此演员表的结果会隐式转换为其他类型。
我的问题是:为什么这个操作会有一个回绕?!
注意:当我使用调试器检查array
的值时:
array [2] =
{
12,
14
}
这是正确的值。
答案 0 :(得分:1)
首先,176 * 1000不适合16位无符号短路。因此,通过使用MISRA,您可以防止代码中出现严重错误,因为算法是在签名int
类型上计算的,其结果隐式显示为无符号短消息。如果你得到预期的结果,那完全是巧合/运气。
请注意,还有其他两个未报告的MISRA违规建议:
stint.h
(规则6.3)这两个都是非常好的规则,而不是你应该忽略的东西。 (另外它应该警告你使用没有' u'后缀的文字。)
修复是用类型安全函数替换凌乱的宏,它不包含隐式促销(给定32位int
):
uint16_t convert (uint16_t x)
{
const uint16_t z = 14745u;
uint32_t result32;
result32 = (uint32_t)x * 1000ul + (uint32_t)z / 2ul / (uint32_t)z
return (uint16_t)result32;
}
答案 1 :(得分:0)
与整体推广有关:
操作时会提升小于int的整数类型 在他们身上表演。如果原始类型的所有值都可以 表示为int,较小类型的值转换为 一个int;否则,它将转换为unsigned int。
这样,宏Convert(206) [((((unsigned short)206*(unsigned short)1000) + ((z) / (USHORT)2)) /(z))]
将按如下方式执行: