Is it possible to right shift a signed variable? (12.7)

6.12 Expressions

Moderators: misra-c, david ward

Post Reply
jbrookley
Posts: 12
Joined: Thu Aug 08, 2013 5:56 pm
Company: Kavlico

Is it possible to right shift a signed variable? (12.7)

Post by jbrookley » Tue Oct 29, 2013 6:01 pm

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: Select all

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: Select all

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<=30u))
{
	ShiftedLong = ShiftedLong >> 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: Select all

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: Select all

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!

Steve Montgomery
Posts: 104
Joined: Fri Sep 17, 2004 1:31 pm
Company: .
Location: Northumberland or Isle of Skye

Re: Is it possible to right shift a signed variable? (12.7)

Post by Steve Montgomery » Tue Oct 29, 2013 8:48 pm

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.

misra-c
Posts: 572
Joined: Thu Jan 05, 2006 1:11 pm

Re: Is it possible to right shift a signed variable? (12.7)

Post by misra-c » Thu Dec 12, 2013 9:06 am

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.
---
Posted by and on behalf of
the MISRA C Working Group

Post Reply

Return to “6.12 Expressions”