tags:

views:

9771

answers:

9
+12  Q: 

Shift operator in C

Is the shift operator (<<, >>) in C arithmetic shift or logical shift?

A: 

It shifts the bits : for example "2 << 1 == 4"

2 in binary is 0010 We shift the bits 1 row to the left : 0100, which gives us 4

mathieu
+14  A: 

When shifting left, there is no difference between arithmetic and logical shift. When shifting right, the type of shift depends on the type of the value being shifted.

(As background for those readers unfamiliar with the difference, a "logical" right shift by 1 bit shifts all the bits to the right and fills in the leftmost bit with a 0. An "arithmetic" shift leaves the original value in the leftmost bit. The difference becomes important when dealing with negative numbers.)

When shifting an unsigned value, the >> operator in C is a logical shift. When shifting a signed value, the >> operator is an arithmetic shift.

For example, assuming a 32 bit machine:

signed int x1 = 5;
assert((x1 >> 1) == 2);
signed int x2 = -5;
assert((x2 >> 1) == -3);
unsigned int x3 = (unsigned int)-5;
assert((x3 >> 1) == 0x7FFFFFFD);
Greg Hewgill
So close, Greg. Your explanation is nearly perfect, but shifting an expression of signed type and negative value is implementation-defined. See ISO/IEC 9899:1999 Section 6.5.7.
Rob Adams
+15  A: 

According to K&R Second edition (the bible) the results are implementation-defined for right-shifts of signed values.

Wikipedia says that C/C++ 'usually' implements an arithmetic shift on signed values.

Basically you need to either test your compiler or not rely on it. My VS2008 help for the current MS C++ compiler says they do an arithmetic shift.

Ronnie
+2  A: 

Well, I looked it up on wikipedia, and they have this to say:

C, however, has only one right shift operator, >>. Many C compilers choose which right shift to perform depending on what type of integer is being shifted; often signed integers are shifted using the arithmetic shift, and unsigned integers are shifted using the logical shift.

So it sounds like it depends on your compiler. Also in that article, note that left shift is the same for arithmetic and logical. I would recommend doing a simple test with some signed and unsigned numbers on the border case (high bit set of course) and see what the result is on your compiler. I would also recommend avoiding depending on it being one or the other since it seems C has no standard, at least if it is reasonable and possible to avoid such dependence.

Mike Stone
A: 

I believe it is a logical shift, in that the bits that are shifted off of the end of the storage (8, 16, 32, 64 bits) are lost. Also, the bits are simply shifted within their container, with no regard for whether it is signed or unsigned.

For example,

5 >> 1 (00000101) = 2 (00000010) This loses the lowest order bit as it drops off the bottom

char c = 64 (01000000); c << 1 = -128 (10000000) 2's compliment is not respected. Just bitwise movement

c << 2 = 0 Highest order bit drops off (No carry bit specifier)

Hope I am clear enough with my explaination.

Xetius
+2  A: 

In terms of the type of shift you get, the important thing is the type of the value that you're shifting. A classic source of bugs is when you shift a literal to, say, mask off bits. For example, if you wanted to drop the left-most bit of an unsigned integer, then you might try this as your mask:

~0 >> 1

Unfortunately, this will get you into trouble because the mask will have all of its bits set because the value being shifted (~0) is signed, thus an arithmetic shift is performed. Instead, you'd want to force a logical shift by explicitly declaring the value as unsigned, i.e. by doing something like this:

~0U >> 1;
Nick
A: 

GCC will typically use logical shifts on unsigned variables and for left-shifts on signed variables. The aritmetic right shift is the truly important one because it will sign extend the variable. GCC will will use this when applicable, as other compilers are likely to do.

Cristián Romo
+1  A: 

here is a function to get a logical right shift of an int in C. Hope this helps you

int logicalRightShift(int x, int n) {
    return (x >> n) & ~(((x >> (sizeof(int) << 3) - 1) << (sizeof(int) << 3) - 1)) >> (n - 1));
}
John Scipione
A: 

برنامج لغة c++للغة المعامل والابات

gamar azhary