MISRA C:2012规则14.4

时间:2018-10-12 13:12:43

标签: c misra

按照MISRA规则 if语句的控制表达式和迭代语句的控制表达式应实质上具有布尔类型

#include <stdbool.h>
#include <stdlib.h>

void foo(void){
    int i = 0;

    if(i){}              /* Non-compliant - int32_t is not boolean */

    if(i != 0){}         /* Compliant */

}

我不明白仅使用该值怎么会导致问题。为什么只添加一个布尔表达式被认为是一种好习惯。 任何见识都会有所帮助

4 个答案:

答案 0 :(得分:9)

基本原理包含以下规则:强类型化。控制表达式本质上应该是布尔类型。相等,关系等运算符的结果应视为基本布尔值,而在int或指针中显示而没有运算符意味着该表达式属于已使用类型。

(作为旁注,这对于与C ++的兼容性可能很重要,在C ++中,许多运算符实际上返回了bool,并且可能会因operator函数的重载而返回bool

但是,MISRA没有提供主要原因,那就是自我记录代码。 if(ptr != NULL)只能是指针与NULL的比较。没有误会的余地。 if(ptr)可以是与NULL的比较,也可以是手指的意外滑动,程序员实际上是指if(*ptr)。另外,如果指针具有一些隐秘的名称,则if(xyz)的作用并不明显,但是if(xyz != NULL)的作用却显而易见。

此规则还可以防止诸如if(func)之类的if(func())之类的错误。请记住,许多MISRA规则都是为了静态分析器而设计的。


关于强类型输入,请考虑以下示例:

#include <stdio.h>
#include <stdbool.h>

int main (void)
{
  int x = false;
  x = ~x;

  if(x)
  {
    puts("x is true");
    if(x!=true)
    {
      puts("but x is not true\n");
    }
  }

  bool y = x;

  if(y)
  {
    puts("y is true");
    if(y==true)
    {
      puts("I swear, y is really true");
    }
  }
}

输出:

x is true
but x is not true

y is true
I swear, y is really true

答案 1 :(得分:4)

  

为什么只添加一个布尔表达式被认为是很好的做法?

” MISRA-C引入了一个强大的类型模型,以帮助用户避免在C类型模型中发生意外问题。 该规则防止在打算使用布尔表达式时意外使用整数表达式。 “ stated in the MISRA forum, as an "official" MISRA C WG answer

  

在if语句中仅使用整数会导致问题吗?

我想不出什么办法,但是在项目中强制执行一致的代码样式和理念也很重要。

答案 2 :(得分:1)

我想不出一个特殊的原因。

我在考虑类型转换方面,例如如果使用双精度d,则可能会出错,但是双精度会被计算为/不为0.0,因此对于if或迭代语句仍然是有效的表达式。或指向字符(字符串)的指针,但在那里也会产生有效的表达式。

所以我能提出的唯一理由是,现在很明显这是一个布尔表达式,即更好的可读性。

例如,如果MISRA也检查第二个操作数是否正确,那将是很好的选择

char *s;
if (s != NULL && *s != '\0')

也可以写成:

if (s != 0 && *s != 0)

,对于双d

if (d != 0.0)

答案 3 :(得分:1)

另一个可能的原因可能是识别潜在的错误,例如:

#include <stdbool.h>
#include <stdlib.h>

void foo(void){
    int i = 0;

    if(i){}              /* Non-compliant - int32_t is not boolean */

    if(i |= 0){}         /* Non-compliant - type is still int32_t */

} 

或更明显的

#include <stdbool.h>
#include <stdlib.h>

void foo(void){
    int i = 0;

    if(i){}              /* Non-compliant - int32_t is not boolean */

    if(i = 0){}         /* Non-compliant */

}