在一个针对 16 位处理器的程序中的巨大宏中,以下代码(简化的)出现了多次:
typedef unsigned short int uint16_t;
uint16_t var;
var = ~0xFFFF;
MISRA 提示警告 12.4:整数转换导致截断。用于获取此信息的工具是 Coverity。
我已经检查过论坛,但我确实需要一个解决方案(而不是通过实际值更改否定),因为这一行位于具有不同参数的宏内。
我尝试了很多事情,这是最后的尝试,但也失败了:
var = (uint16_t)((~(uint16_t)(0xFFFFu))&(uint16_t)0xFFFFu);
(值0xFFFF只是一个例子。在实际代码中,该值是一个变量,可以取任何值(但16位))
请问您还有其他想法吗?谢谢。
编辑:
然后我尝试使用32位值,结果与以下代码相同:
typedef unsigned int uint32_t;
uint32_t var;
var = (uint32_t)(~(uint32_t)(0xFFFF0000u));
最佳答案
摘要:
假设您使用 MISRA-C:2012 静态分析器,您应该会收到违反规则 10.3 和 7.2 的警告。
规则 12.4 仅涉及无符号整型常量的环绕,这种情况只能与二元 + 和 - 运算符一起出现。这里似乎无关紧要。
警告文本对于 MISRA-C:2004 12.4 和 MISRA-C:2012 12.4 似乎都没有意义。该工具可能显示错误的警告。
但是,MISRA:2012 规则 10.3 禁止将值分配给类型小于表达式中预期类型的变量。
要使用 MISRA 术语,~0xFFFF
的基本类型是无符号的,因为十六进制文字的类型为 unsigned int
。在您的系统上,unsigned int
显然大于 uint16_t
(int 是标准 6.3.1.1 中比短整型“排名更高”的整数类型,即使它们属于尺寸相同)。也就是说,uint16_t
的基本类型比 unsigned int
更窄,因此您的代码不符合规则 10.3。这是您的工具应该报告的内容。
隐藏在 MISRA 术语背后的实际技术问题是 ~
运算符很危险,因为它带有隐式整数提升。这又会导致像这样的代码
uint8_t x=0xFF;
~x << n; // BAD, always a bug
当值 0xFFFFFF00 左移时调用未定义的行为。
因此,将 ~
运算符的结果转换为正确的预期类型始终是一种良好的做法。 MISRA 2004 中甚至对此有明确的规则,现已合并到“基本类型”规则中。
此外,MISRA (7.2) 规定所有整数常量都应具有 u
或 U
后缀。
符合 MISRA-C:2012 的代码如下所示:
uint16_t var;
var = (uint16_t)~0xFFFFu;
或者过于迂腐:
var = (uint16_t)~(uint16_t)0xFFFFu;
关于c - MISRA 警告 12.4 : integer conversion resulted in truncation (negation operation),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40377804/