Search code examples
cmisra

MISRA-C:2012 warning of Rule 10.8 "being cast to a wider type"


I got a MISRA-C warning of Rule 10.8: A composite expression of 'essentially unsigned' type (unsigned char) is being cast to a wider unsigned type, 'unsigned short'.

This warning was detected with the following code.

void Fucntion(unsigned char isSwitchOn) {
    unsigned short switchMask = 0U;

    switchMask |= (unsigned short)(isSwitchOn & 1U) << 1;

Why was a warning detected? Also, does this code cause problems?

I think that the expression (isSwitchOn & 1U) is converted to an int type and calculated, and the result is truncated and stored as an unsigned short type. Thinking like that, the warning seems unnatural to me.


Solution

  • Why was a warning detected?

    Let us look at

    void Fucntion(unsigned char isSwitchOn) {
      unsigned short switchMask = 0U;
      switchMask |= (unsigned short)(isSwitchOn & 1U) << 1;
    
    1. isSwitchOn, being lower rank than 1U, goes through the usual arithmetic conversion (C11 §6.5.10 3) to the type unsigned to match the type of 1U.

    2. isSwitchOn & 1U is calculated, the result type is unsigned.

    3. Cast (unsigned short) is applied to the unsigned result - this step seems strange. This is the MISRA-C warning of Rule 10.8. There is no need for the cast. The composite type unsigned is unnecessarily being narrowed to unsigned short.

    4. The (unsigned short) result is prepared for shifting and integer promotions are performed on each of the operands of the <<. So the (unsigned short) is promoted to int or possibly unsigned if USHRT_MAX > INT_MAX. Let us assume int.

    5. Now the shift of an int occurs. Result is type int.

    6. The int is applied to a unsigned short.


    Also, does this code cause problems?

    I do not see in this case, the cast causing an issue other than it is WET programing. Had the result been unsigned switchMask, yes then the shifted out bit would have been lost.

    It makes more sense to cast the result after the shift. @Myst

    switchMask |= (unsigned short)((isSwitchOn & 1U) << 1);
    

    Or avoid other potential warnings with

    switchMask = (unsigned short)(switchMask | ((isSwitchOn & 1U) << 1));
    

    I think that the expression (isSwitchOn & 1U) is converted to an int type and calculated

    No, the expression (unsigned short)(isSwitchOn & 1U) is converted to an int type and calculated.


    Note: It is dubious that unsigned char isSwitchOn and unsigned short switchMask are not the same type.