如何转换表达式以摆脱QAC警告?

时间:2016-02-25 14:41:17

标签: c gcc c99 static-analysis c89

我正在使用QAC,我收到相应源代码行的以下消息。我如何施展它以使QAC能够理解"它?

使用的编译器是gcc - 它没有警告这个问题,因为它设置为" iso c99"。

#define DIAGMGR_SIGNED_2_BYTES_178           ((s16)178)

sK  = (s16)(sE1 / DIAGMGR_SIGNED_2_BYTES_178);
                  ^
  

签署除法或余数运算的结果可能是实施   定义

  

正在执行分组(' /')或余数('%')操作   有符号整数类型,结果可能是实现定义的。   为整数除法或余数生成消息3103   签名类型的操作,其中:

     
      
  • 一个或两个操作数是非常量和有符号整数类型,或
  •   
  • 两个操作数都是整数常量表达式,一个是负值,另一个是正值
  •   
     

有符号整数除法或余数运算,其中一个操作数   是积极的而另一个是消极的可以在两个中的一个中执行   方法:

     
      
  • 除法将向零舍入,任何非零余数将为负值
  •   
  • 除法将从零开始舍入,任何非零余数都是正值在ISO:C99标准中,第一种方法是   总是用的。在ISO:C90标准中,可以使用任何一种方法 -   结果是实现定义的。例如:
  •   
     

/ PRQA S 3120,3198,3408,3447 ++ /

extern int r;

extern int si;

extern void foo(void)
{
    r = -7 / 4;     /* Message 3103 *//* Result is -1 in C99 but may be -2 in C90 */

    r = -7 % 4;     /* Message 3103 *//* Result is -3 in C99 but may be  1 in C90 */
    si = si / r;    /* Message 3103 */
}

1 个答案:

答案 0 :(得分:2)

您需要配置该工具,以便它了解您的代码是C99。在旧的C90标准中,负数的划分可以用两种不同的方式实现,see this。这是一个已知的" bug"在C90标准中,自C99以来已经修复。

这是大多数静态分析工具的标准警告,特别是如果它们设置为检查MISRA-C合规性。 MISRA-C:2004和2012都要求程序员知道这个C标准" bug"。

C90中的解决方法:

如果你确定操作数不是负数,只需将它们转换为无符号类型,或者使用无符号类型开始。

如果您知道操作数可能是负数:

  • 如果任一操作数为负数,请设置标志以指示它是哪一个。
  • 取两个操作数的绝对值。
  • 对绝对值进行分割。
  • 重新添加数字符号。

不幸的是,这是C90中唯一的便携式解决方案。或者,您可以添加静态断言,以防止代码在向下截断负数的系统上进行编译。

如果您使用的是C99,则不需要解决方法,因为它总是截断为零。然后,您可以安全地禁用警告。