Why did my tool throw a MISRA error here?

前端 未结 4 1678
死守一世寂寞
死守一世寂寞 2021-01-18 16:18

What can I do to avoid MISRA giving this error for the code below? I tried casting with (unit16_t). But then it didn\'t allow an explicit conversion.

Illegal implici

4条回答
  •  -上瘾入骨i
    2021-01-18 16:34

    The problem is that both rate and percentage are silently promoted by the integer promotions to type "int". The multiplication is therefore performed on a signed type.

    MISRA compatible code is to either rewrite the code as

     uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;
    

    or do as MISRA suggests, immediately typecast the result of an expression to its "underlying type":

     uint16_t basic_units = (uint8_t)(rate * percentage);
    

    EDIT: Clarification follows.

    ISO 9899:1999 6.3.1.1 2

    If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.

    Informative text from MISRA-C:

    MISRA-C:2004 6.10.3 Dangerous type conversions:

    /--/

    - Change of signedness in arithmetic operations: Integral promotion will often result in two unsigned operands yielding a result of type (signed) int. For example, the addition of two 16-bit unsigned operands will yield a signed 32-bit result if int is 32 bits but an unsigned 16-bit result if int is 16 bits.

    I'm actually not sure whether the 2nd line of mine above would satisfy MISRA or not, at second thought I may have confused MISRA 10.1 with 10.5, where the latter enforces an immediate cast to underlying type, but only in case of certain bitwise operators.

    I tested both lines with LDRA static code analysis and it didn't complain (but gives some incorrect, non-related warnings), but then LDRA also performs very poorly at MISRA-C.

    Anyway, the problem in the original question is that rate and percentage are both implicitly converted by the integer promotions to type int which is signed, since int can represent all values of a uint8_t. So it becomes

    uint16_t basic units = (int)rate * (int)percentage.
    

    To prevent this you have to typecast explicitly. After giving it more thought, I'd go with the 1st line of my two above.

提交回复
热议问题