MISRA 违反 C 代码中的三元运算符

问题描述

我已经为以下用 C 编写的代码运行了 MISRA。我有一个三元运算符来查找输入类型。这是我写的一段代码

typedef enum{
    type0 = 0,type1,type2
}my_values;

#define get_type() (uint8)((bool_type0()) ? (type0) : ( (bool_type1()) ?  type1 : type2  ))

/* Here bool_type0() and bool_type1() are outside functions which return bool values */

function1 ()
{
    uint8 type_value = 0U;

    type_value = get_type();

    if((type_value == type0) || (type_value == type1 ))
    {
        //update the logic
    }
    else
    {
        //update the logic
    }
} 

运行 MISRA 后,我收到以下警告:

  1. 在这type_value = get_type(); 我收到警告

    三元运算符的第一个操作数具有不适当的基本类型“无符号字符”

  2. 在 if 循环中,我收到警告

    运算符“==”的操作数没有相同的基本类型类别:一个是“无符号”,另一个是“枚举”

我不明白第一个警告有什么问题。在第二个警告中,如何将枚举更改为无符号值?我想我必须将两个操作数都更改为无符号值。在不更改枚举类型的情况下,如何修复这些错误?有什么建议吗?

解决方法

三元运算符的第一个操作数具有不适当的基本类型“无符号字符”

第一个操作数需要是布尔值。您的工具没有意识到代码中对应于 boolean in 的类型。

需要配置 MISRA-C 的每个静态分析器,以便它知道哪种类型是布尔类型,因为它向后兼容没有布尔类型的 C90。如果您使用的是 bool_Bool,那么您必须这样做是非常糟糕的,但这显然是您选择的工具的工作方式。

运算符“==”的操作数没有相同的基本类型类别:一个是“无符号”,另一个是“枚举”

这是一个正确的诊断,您不应该将枚举(枚举变量或枚举常量)与 MISRA-C 合规性的整数值进行比较,而只能与它们自己的枚举类型进行比较。您需要研究 MISRA-C:2012 中的基本类型规则才能理解这一点,有一个方便的表格,您可以在其中查看某个运算符的哪些类型可以/不能与哪些其他类型一起使用。

很容易修复:(my_values)type_value == type0

,

让我们分解一下...

  1. 您将 type_value 声明/定义为 uint8

uint8 type_value = 0U;

  1. 那么你正在使用那个凌乱的宏...

    #define get_type() (uint8)((bool_type0()) ? (type0) : ( (bool_type1()) ? type1 : type2 ))

    /* 这里 bool_type0() 和 bool_type1() 是返回 bool 值的外部函数 */

    type_value = get_type();

所以让我们扩展宏...

type_value = (uint8)( ( bool_type0() )
           ? ( type0 )
           : ( ( bool_type1() ) ? type1 : type2 ) )

首先,当 type_value 包含枚举值时,为什么它是 uint8...将其声明为 enum my_values

除此之外,我看不出任何明显错误,部分是由于不必要且令人困惑的宏。

enum my_values type_value = bool_type0() ? type0 : ( bool_type1() ? type1 : type2 );

这表明您的工具没有正确配置用于检测布尔值...并且将 bool(实际上是 uint8_t,它是一个 unsigned char)视为一个,错误,{{ 1}}。

,

我就是这么写的。

typedef enum{
    type0 = 0,type1,type2
} my_values;

/* Here bool_type0() and bool_type1() are outside functions which return bool values */
my_values get_type(void)
{
    my_values ret_val = type2;
    
    if (bool_type0())
    {
        ret_val = type0;
    } 
    else if (bool_type1())
    {
        ret_val = type1;
    } 
    else
    { 
        /* no need,type2 by default */
    }

    return ret_val;
}

function1 ()
{
    my_values type_value = get_type();

    if((type_value == type0) || (type_value == type1 ))
    {
        //update the logic
    }
    else
    {
        //update the logic
    }
} 
,

很可能是您的 linter 报告的误报。

在黑暗中的一些猜测让 linter 高兴。

  1. 尝试将三元的所有元素强制为 uint8:

将您的宏定义为:

#define get_type() (bool_type0() ? (uint8)type0 : bool_type1() ? (uint8)type1 : (uint8)type2)
  1. 可能是枚举声明中的 =0 把它扔掉了。尝试在没有它的情况下声明枚举:

这个:

typedef enum{
    type0,// should default to 0
    type1,type2
}my_values;

或所有显式:

typedef enum{
    type0 = 0,type1 = 1,type2 = 2
}my_values;
  1. 最后,我很惊讶您没有收到关于 function1 没有明确返回类型的警告。我想知道您的函数定义中缺少指定的返回类型是否会导致 linter 关闭。将其明确标记为具有 void 返回类型:

试试这个:

void function1()
{
     ....