MISRA Discussion Forums

Full Version: Is it possible to right shift a signed variable? (12.7)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello everyone,

I have an application that I need to right shift a signed variable but it seems to be giving me some issues. My initial line was:

Code:
typedef unsigned char uchar8;
typedef signed long slong32;

slong32 Shifted Long;
uchar8 NumBitsShift;

ShiftedLong >>= NumBitsShift - 1u;

Due to various MISRA C requirements, the code has morphed into this ridiculous block:

Code:
typedef unsigned char uchar8;
typedef signed char schar8;
typedef signed long slong32;

slong32 Shifted Long;
uchar8 NumBitsShift;
uchar8 tempchar = 0;
slong32 templong = 0;

tempchar = (uchar8)(NumBitsShift - 1u);

if((tempchar>=1u)&&(tempchar> tempchar; /* MISRA C 12.7 Error here */
}

On the flagged line, I get the error "Underlying type of LHS operand bitwise operator is signed type: ShiftedLong". I've tried fixing that by casting the tempchar as shown below:

Code:
ShiftedLong = ShiftedLong >> (slong32)tempchar;

I even tried to go completely over the top with plans to scale it back once I isolate the problem by doing this:

Code:
ShiftedLong = (slong32)((slong32)ShiftedLong >> (slong32)tempchar);

It appears, I am still having the same problem. What it now appears, based on this, is that it is not possible to right shift a signed variable. Is this true or is there a way around this?

Any help you can give me would be appreciated. Thanks!
Rule 12.7 prohibits shifting of signed types because the result depends on how your compiler chooses to represent types and how it performs shifts. The specific problem with right shifting a signed value is that the compiler is free to choose whether the sign bit is filled with 0 or filled with copies of the sign bit. So (in binary) 10... >> 1u could either be 01... or 11... (where the ... represent least significant bits).

As is the case with several MISRA C rules, the purpose behind this rule is to make programmers think about what they want to achieve and then code it appropriately.

If you want to guarantee that 0 is shifted into the vacated bits then you could cast the signed variable to an unsigned version, perform the shift, and then cast the result back. This works because conversion of signed to unsigned of the same size won't change the bit pattern (on a 2s complement machine at least) and the result will be guaranteed to fit in the signed type as it will be no larger than the original value.

If you want to copy the sign bit into the vacated bits then check the documentation for your compiler. It should tell you somewhere whether right shifts on signed quantities preserve the sign bit or not. If they do, then I would recumbent raising a deviation against this rule on the grounds that your implementation guarantees to do exactly what you want. If you aren't able to raise a deviation, or your implementation doesn't preserve the sign bit, then I think you'll need to write a function to achieve what you want, possibly or even probably in assembly language.
The first two paragraphs of the answer given by Steve Montgomery have given a good summary of why shifting on signed integers can give problems.

Any shift on a signed integer will violate rule 12.7, because of the implementation defined behaviour of such shifts.