2

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 ?

Lundin
  • 195,001
  • 40
  • 254
  • 396
HS94
  • 23
  • 3
  • I'm not sure what it is that you are wondering about. Is it `bit` having different type than `in` or is it the `& 1u` part? – Gerhardh Jan 15 '21 at 08:24
  • Both. 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 ? – HS94 Jan 15 '21 at 08:27
  • 2
    bit is how many you shift on right, this does not have to be the same type as in. – OznOg Jan 15 '21 at 08:29
  • 4
    Why would you require `bit` to have same type? If you shift an `unsigned long long` why would you need `bit` to be as large? It is sufficient that `bit` can hold the number of bits needed. Regarding the `&`: Do you know about integer type promotion? The smaller operand will be promoted to the larger type. – Gerhardh Jan 15 '21 at 08:29
  • 2
    the result of `((in >> bit) & 1u)` is `unsigned int`, not `unsigned short` – phuclv Jan 15 '21 at 08:35
  • @Gerhardh Ahh okay thanks. I wasn't aware about the integer type promotion. But then i don't understand following why am i getting the violation 10.1 unpermitted operand & and 10.4 mismatched essential type when i am doing follwing ((in >> bit) & 1u) in = unsigned int and bit = 5 (int) – HS94 Jan 15 '21 at 08:50
  • Generic Note: misra has different ideas what might be good or bad code than the c standard. This is a completely different question than what you have actually asked. Or even 2 different questions than the 2 questions you asked here. – Gerhardh Jan 15 '21 at 08:57
  • When you say "MISRA is not complaining", which tool is that? – Lundin Jan 15 '21 at 09:15

1 Answers1

2

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • @QuyNguyen2013 What, more precisely? And why? Because you say so, or because you care to quote a technical source? – Lundin Jan 18 '21 at 07:17
  • It is incorrect according to the MISRA C standard, as published by MISRA, which is the Motor Industry Software Reliability Association – QuyNguyen2013 Jan 19 '21 at 21:31