Home > Mobile >  MISRA C2012:10.8 violation in the sample code
MISRA C2012:10.8 violation in the sample code

Time:03-06

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;
    /* 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; 
} 

I have no idea to solve 10.8, does someone can explain and fix it, thank you very much.


MISRA C:2012 Rule 10.8 The value of a composite expression shall not be cast to a different essential type category or a wider essential type
Description
Rule Definition
The value of a composite expression shall not be cast to a different essential type category or a wider essential type.

CodePudding user response:

MISRA C:2012 Rule 10.8 states:

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

Looking at your code:

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

Lets see...

  • output is a uint16
  • The right hand side is cast to uint16
  • The right hand side is a composite expression in sint32

So:

output = (uint16)( composite expression in sint32 )

Yes, you are NOT violating the guideline R.10.8 because of width - you are casting to a narrower type; however you are violating by casting signed to unsigned within the composite expression.

You have three choices...

  1. Deviate the rule
  2. Modify so that output is sint32 and do all calcs in signed
  3. Are the X and M values all unsigned? Could the calculation be performed in uint32 or uint16?

See profile

CodePudding user response:

There are multiple problems in this line of code:

output = (uint16)(((deltaOut / deltaIn) * ((sint32)(pcurData->temperature) - (sint32)(pTableData[idx-1].temperature)))   (sint32)pTableData[idx-1].Setdata);
  • MISRA C:2012 Rule 10.8 states that you should not cast the value of a composite expression to a different essential type category or a wider essential type: the composite expression is the whole interpolation expression and the different essential type is uint16, which is probably a typedef on unsigned short. You could use an intermediary variable output32 to store the sint32 result and cast that as output = (uint16)output32;.

  • Yet this MISRA warning is hiding a much more important problem: the scale operation should be computed as A * B / C with a type large enough to handle A * B, not (A / C) * B using integer arithmetics where rouding will reduce the precision.

If deltaOutis known to be in the range of sint16, you could write:

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;

Otherwise, you might need 64-bit arithmetics:

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;

If the target has fast floating point hardware, you could compute the interpolation in floating point with float or double arithmetics:

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;

As a rule of thumb, avoid long expressions, define variables for intermediary results and choose their type carefully to avoid overflow or precision loss.

Another remark: what is idx in your function? It seems to be a global variable. You should avoid global variables, especially with such a bland short name.

  • Related