1

I'm troubleshooting some code and I encountered this line

uint8var = ((constUint8[0]) >> 7) & 0x01u;

I was wondering what the correct practice in this is. Is the & 0x01u necessary for proper implementation when writing MISRA compliant code, considering I'm shifting uint8 by 7 digits to the right?

user145760
  • 124
  • 9
  • I don't see what your concern is. Can you elaborate? – John Bollinger Apr 12 '19 at 12:09
  • I don't know if it's a correct practice, though `& 1` would be far more readable IMO, and if `constUint8[0]` is 8 bits, the whole operation is redundant. – joH1 Apr 12 '19 at 12:12
  • My compiler turns `(x >> 7) & 0x01`, `x >> 7`, and `!!(x & 0x80)` (Where `x` is an unsigned char) into the same instruction... when in doubt, check the assembly. – Shawn Apr 12 '19 at 12:16
  • 3
    @Shawn: Checking assembly code does not answer the question about whether this code complies with MISRA rules. MISRA is concerned with whether source code will produce the desired results under all applicable C implementations. The fact that one implementation produces the desired result in one situation does not demonstrate the desired property. – Eric Postpischil Apr 12 '19 at 12:24
  • What are the types of the variables, `uint8_t`? – Lundin Apr 12 '19 at 12:52

1 Answers1

2

Right-shifting a uint8_t can never be problematic in itself. However, MISRA-C aims to block you from writing bugs caused by implicit integer promotion. In your case constUint8[0] will get implicitly promoted to int which is signed. This will cause various MISRA compliance problems that are easiest avoided by ensuring your code contains no implicit promotions in the first place.

When it comes to shifts, that means casting to a large integer type before shifting:
(uint32_t)constUint8[0] >> 7.

The mask with 0x01u is superfluous and adds no value. It can be safely removed. To achieve MISRA-C compliance, the best way is to re-write the code like this:

uint8var = (uint8_t) ((uint32_t)constUint8[0] >> 7);

where the (uint8_t) cast ensures that there's no implicit conversion, but that we explicitly go back to the intended type. MISRA-C doesn't allow implicit assignment from larger types to smaller ones.

For more info see Implicit type promotion rules.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Why does MISRA-C accept a cast to `uint32_t` as sufficient to avoid promotion to a signed integer? I am curious about the assumptions it is making, or the environments it is constraining itself to. – Eric Postpischil Apr 12 '19 at 14:55
  • @EricPostpischil It doesn't, I'm just making an assumption that this is a real-world computer where int is either 16 or 32 bits. – Lundin Apr 14 '19 at 07:42