Misra and bit operations

Viewed 517

I have some understanding problems of misra and bitwise operations.

I have following operation:

((in >> bit) & 1u)

Here in has the type unsigned short and bit has the type int. 1u should be an unsigned int in my understanding.

First I dont understand why misra is not complaining that the bit shift is done with an signed bit with a diffrent type and I don't understand why the bit operation between an unsigned short which should be the outcome of (in >> bit) & 1u is allowed.

Updated for clarifying the question: Why is it allowed that the bit has a diffrent type then in ?
Shouldn't it cause a mismatched type ?
Can it not cause problems if I bit shift with a 32 bit 1 into an 16 bit in ?
And also the second part. the outcome of the bitshift is an unsigned short so the bit operation is performed with an 16 bit short and an 32 bit int. Is that not a problem ?

1 Answers

Assuming 32 bit int type, then:

MISRA-C:2012 just requires that the type the operands of a shift operator must be "essentially unsigned" (rule 10.1). By that they imply that an implicit promotion from unsigned short to int can never be harmful, since the sign bit can't be set by that promotion alone.

There's further requirement (MISRA-C:2012 rule 10.4) that both operands in an expression where "the usual arithmetic conversions" are performed (see Implicit type promotion rules) should be of the same essential type category. "The usual..." apply to most binary operators in C, but not to the shift operators, they are a special case.

For the shift operators, the C standard 6.5.7 lists this special rule:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand.

This means that some_unsigned_short >> is MISRA-C compliant and the type of bit is actually irrelevant (as long as it is a positive number). However, rule 10.1 requires that the right operand must be unsigned too (to prevent nonsense stuff like >> -1). Even if the right operand is also unsigned, the expression is a bit questionable still - preferably you should cast the left operand to a large integer type (like uint32_t) before shifting.

Ignoring the right operand of shift, (some_unsigned_short >> some_int) & 1u is still not MISRA-C compliant, because it is mixing signed and unsigned essential type categories int & unsigned int which is not allowed neither by rule 10.1 nor rule 10.4 - the & operator does apply the usual arithmetic conversions. So this needs to be fixed to either

(uint32_t)(some_unsigned_short >> some_unsigned_int) & 1u

or preferably

((uint32_t)some_unsigned_short >> some_unsigned_int) & 1u

Either is MISRA compliant.


However, in the case you have 16 bit int everything turns different. The unsigned short operand of the shift then gets integer promoted to unsigned int rather than int, as a special case in the integer promotion rule (the link I gave above explains that special case). In that case, after promotion we end up with some_unsigned_int >> ..., which is fine. And then (some_unsigned_int >> ...) & 1u is fine too.

Related