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 auint16
- 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...
- Deviate the rule
- Modify so that
output
issint32
and do all calcs in signed - Are the X and M values all unsigned? Could the calculation be performed in
uint32
oruint16
?
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 onunsigned short
. You could use an intermediary variableoutput32
to store thesint32
result and cast that asoutput = (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 handleA * B
, not(A / C) * B
using integer arithmetics where rouding will reduce the precision.
If deltaOut
is 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.