示例代码中 MISRA C2012:10.8 违规

MISRA C2012:10.8 violation in the sample code

typedef struct{
    sint16 temperature;
    uint32 Setdata;
} VariableA;

VariableA TableData[N];

static uint16 linearinterpolation(const currentdata *pcurData,const VariableA* pTableData)
{   /* Declare local variables */
    sint32 deltaOut;
    sint32 deltaIn;
    uint16 output;
    uint16 idx;
    /* DeltaIn of  temperatures. */
    deltaIn = (sint32)(pTableData[idx].temperature) - (sint32)(pTableData[idx-1].temperature);
    /* DeltaOut of  Setdata */
    deltaOut = (sint32)pTableData[idx].Setdata - (sint32)pTableData[idx-1].Setdata;
    /* Division by 0 protection. */
    if (deltaOut == 0)
    {   /* if the division == 0 */
            output = pTableData[idx-1].Setdata;
    }
    else
    {   /*MISRA C:2012 Rule 10.8 */ 
        output =(uint16)((( deltaOut / deltaIn) *((sint32)(pcurData->temperature) - (sint32)(pTableData[idx-1].temperature))) + (sint32)pTableData[idx-1].Setdata );
    }
    return output; 
} 

我不知道解决10.8,有谁能解释和修复它,非常感谢。


MISRA C:2012 规则 10.8 复合表达式的值不应转换为不同的基本类型类别或更广泛的基本类型
说明
规则定义
复合表达式的值不应转换为不同的基本类型类别或更广泛的基本类型。

MISRA C:2012 规则 10.8 规定:

The value of a composite expression shall not be cast to a different essential type category or a wider essential type

查看您的代码:

output = (uint16)( ( ( deltaOut / deltaIn )
                   * ( (sint32)( pcurData->temperature) - (sint32)(pTableData[idx-1].temperature) ) )
                 + (sint32)pTableData[idx-1].Setdata );

让我们看看...

  • output 是一个 uint16
  • 右侧转换为 uint16
  • 右边是sint32
  • 中的复合表达式

所以:

output = (uint16)( composite expression in sint32 )

是的,你没有因为宽度而违反准则 R.10.8 - 你正在投射到更窄类型;但是,您在复合表达式中将 signed 强制转换为 unsigned 是违规的。

你有三个选择...

  1. 偏离规则
  2. 修改 outputsint32 并在带符号的
  3. 中进行所有计算
  4. X和M值都是无符号的吗? uint32uint16可以计算吗?

查看个人资料

这行代码存在多个问题:

output = (uint16)(((deltaOut / deltaIn) * ((sint32)(pcurData->temperature) - (sint32)(pTableData[idx-1].temperature))) + (sint32)pTableData[idx-1].Setdata);
  • MISRA C:2012 规则 10.8 声明您不应将复合表达式的值转换为不同的基本类型类别或更广泛的基本类型:复合表达式是整个插值表达式并且不同的基本类型是 uint16,它可能是 unsigned short 上的 typedef。您可以使用中间变量 output32 来存储 sint32 结果并将其转换为 output = (uint16)output32;.

  • 然而,这个 MISRA 警告隐藏了一个更重要的问题:缩放操作应该计算为 A * B / C,类型足够大以处理 A * B,而不是 (A / C) * B 使用整数算法,其中四舍五入会降低精度。

如果已知deltaOutsint16的范围内,你可以这样写:

sint32 deltaTemp = (sint32)pcurData->temperature - (sint32)pTableData[idx-1].temperature;
sint32 adjust32 = deltaOut * deltaTemp / deltaIn;
sint32 output32 = pTableData[idx-1].Setdata + adjust32;
output = (uint16)output32;

否则,您可能需要 64 位算法:

sint32 deltaTemp = (sint32)pcurData->temperature - (sint32)pTableData[idx-1].temperature;
sint64 adjust64 = (sint64)deltaOut * (sint64)deltaTemp / (sint64)deltaIn;
sint32 output32 = pTableData[idx-1].Setdata + (sint32)adjust64;
output = (uint16)output32;

如果目标具有快速浮点硬件,您可以使用 floatdouble 算法计算浮点插值:

sint32 deltaTemp = (sint32)pcurData->temperature - (sint32)pTableData[idx-1].temperature;
double adjust64 = (double)deltaOut * (double)deltaTemp / (double)deltaIn;
sint32 output32 = pTableData[idx-1].Setdata + (sint32)adjust64;
output = (uint16)output64;

根据经验,避免长表达式,为中间结果定义变量并仔细选择它们的类型以避免溢出或精度损失。

再说一句:你函数里的idx是什么?它似乎是一个全局变量。你应该避免使用全局变量,尤其是这样一个乏味的短名称。