shift right arithmetic operator

Generic
March 9, 2006 at 22:52:48
Specs: XP PRO, 512 DDR 2700

Is there a shift right arithmetic operator in c? There are the shift right and left logical operators <<, and >>. But the arithmetic shift right is different in that it keeps the highest order bit the same (preserving the sign of the number). I guess I could just do this:

unsigned int sra(unsigned int num, int shift)
{
if ((num & 0x80000000) == 0x80000000)
{

for (int count = 0; count < shift; count++)
{
num = (num >> 1) | 0x80000000;
}
return num;
}

return (num >> shift);


}

But that adds alot of complication. Anyways I read that there is an arithmetic shift but I dont know if there is a built in operator for it and can't seem to find a definitive answer on google.


See More: shift right arithmetic operator

Report •


#1
March 10, 2006 at 22:47:43

If I understand correctly, then the shift operators in C/C++ actually are arithmetic shifts. For example if you do this:

int a = 0x80008000;
// a = 1000 0000 0000 0000 1000 0000 0000 0000
int b = a >> 2;
// shift right by 2

Then b will equal 0xE0002000 (1110 0000 0000 0000 0010 0000 0000 0000). This shows that the most significant bit is being maintained.

Does that seem right, or are you trying to do something different?


Report •

#2
March 11, 2006 at 06:35:49

You are right. The data type that I am shifting however is an unsigned int and I think that is what is causing my confusion. I guess that in c++ different data types overload the shift >> operator differently. For instance since an unsigned int has no sign then

unsigned int a = 0xFFFFFFFF;
printf ("%08X\n",a);
a = (a >> 2);
printf ("%08X\n",a);

the shift is a logical shift in the above example because there is no sign bit to preserve even though the high order bit is 1. So in the above example the second printf displays a as 0x3FFFFFFF and the one is not carried over.

So there is a built in logical shift operator (>>) but no arithmetic operator when talking about unsigned ints. To do an arithmetic shift on an unsigned int I guess there would be no built in operator for it because there is no good reason for there to be one. I will use my function from the first post as I think it works fine.


On second thought, maybe I could use a union and then I can logically shift or arithmetically shift it easier. Something like this:

union UNION
{
int signed;
unsigned int unsigned;
};

...
union UNION a;
a.unsigned = 0x12345678;

a.unsigned >> 1; //logical shift
a.signed >> 1; //arithmetic shift
...

Thank you - you helped me clear up my mistake.


Report •

#3
March 12, 2006 at 07:20:08

geohoffman49431,

Both the function and union will work. I have personally tested the union method and find it very satisfactory. After years of programming, I don't guess I'd ever really worried about such a thing since I usually use shifting for bit flags (in which case you'd only want logical shifting), but there might be times that I would want arithmetic shifting. Thanks for posting such an interesting topic and finding a cool solution using the union operator.

Stephen


"Live long and PROGRAM......or at least do _something_ with all that time...!"


Report •

Related Solutions

#4
March 12, 2006 at 22:01:17

Thanks for the reply Stephen. I agree - most of the time I use bitwise & and | to get at the individual flags. But like you said sometimes it is useful to do a logical shift on a signed integer and using unions is a big help. The only problem with unions is they can lead to unportable code if data structures are different sizes on different machines. For instance the word size of a machine might be 16, 32, 64, or 128 bits so the following union might act unpredictably on different machines.

union UNION
{
int i;
double d;
};

I have a comp sci project where I am supposed to simulate all the internal registers of a SPARC processor. Then based on the op code the proffesor supplies I have to update the registers. The registers have to be stored as 32 bit unsigned integers and two of the fifteen or so operations I have to implement are SRL (shift right logical) and SRA (shift right arithmetic). I think I will use the union method as it takes less lines of code and I know the unsigned int and the signed int are the same size on the target machine. Cheers.


Report •

#5
March 13, 2006 at 04:54:28

Yeah,

Refreshing to get something interesting. And well written, no less.


If at first you don't succeed, you're about average.

M2


Report •

#6
March 26, 2006 at 14:12:39

I havent tried, but wont:

unsigned int a = 0xFFFFFFFF;
a = (unsigned int)(((int)a) >> 2);

do what you want? The compiler will "think" it's shifting a signed integer and do sign extension(?) The left-lost cast is probably not necessary but will save you a warning.

/John


Report •


Ask Question