C语言 MISRA警告12.4:整数转换导致截断(求反操作)



在我的一个针对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大(在6.3.1.1标准中,int是比short"排名更高"的整数类型,即使它们的大小相同)。也就是说,uint16_tunsigned int具有更窄的基本类型,因此您的代码不符合规则10.3。这是你的工具应该报告的内容。

隐藏在MISRA术语背后的实际技术问题是,~运算符是危险的,因为它带有隐式整数提升。这反过来又会导致诸如

之类的代码
uint8_t x=0xFF; 
~x << n; // BAD, always a bug
当值0xFFFFFF00左移时,

调用未定义的行为。

因此,将~操作符的结果强制转换为正确的预期类型始终是一种良好的做法。在MISRA 2004中甚至有一个明确的规则,现在已经合并到"基本类型"规则中。

此外,MISRA(7.2)规定所有的整型常量都应该有一个uU后缀。

MISRA-C:2012兼容的代码看起来像这样:

uint16_t var;
var = (uint16_t)~0xFFFFu;

或过于迂腐:

var = (uint16_t)~(uint16_t)0xFFFFu;

当编译器查看右侧时,首先看到的是文字0xFFFF。它会自动提升为一个32位的整数(从警告中可以明显看出)。现在我们可以将该值想象为0x0000FFFF(整32位)。当编译器对它执行~操作时,它变成0xFFFF0000(整32位)。当您编写var = ~0xFFFF;时,编译器实际上会在赋值操作之前看到var = 0xFFFF0000;。当然,在赋值过程中会出现截断

相关内容

  • 没有找到相关文章

最新更新