Reputation: 43
in order to realize logical right shift in c , i search the web and got the following C code
int a, b, c;
int x = -100;
a = (unsigned) x >> 2;
b = (0xffffffff & x) >> 2;
c = (0x0 | x ) >> 2;
now both a and b were logical right shift result(1006632960), but c was still arithmetic shift result(-25), could somebody explain why ? thx
Upvotes: 1
Views: 362
Reputation: 12943
It's all about the operand type of the operator >>
. If it's signed
- the right-shift sets the MSB to 1 if the operand was negative. If the operand is unsigned
- MSB bits are always zero after right-shift.
In your first expression the operand is cast explicitly to unsigned
.
In the second expression the (0xffffffff & x)
us unsigned, because 0xffffffff
definitely represents an unsigned integer (it's an overflow for signed
).
OTOH in the third example 0x0
is signed
(this is the default for integer constants). Hence the whole operand (0x0 | x )
is considered signed
Upvotes: 0
Reputation: 52284
(unsigned) x
is of type unsigned int so it get a logical shift.
0xffffffff
(assuming 32 bit int) is of type unsigned int, so (0xffffffff & x)
is also of type unsigned int so it get a logical shift.
0x0
is of type int, so (0x0|x)
is of type int and get an arithmetic shift (well, it is implementation dependent).
Upvotes: 1
Reputation: 23332
b = (0xffffffff & x) >> 2;
Assuming that your ints are 32 bits, the type of the literal constant 0xffffffff
is unsigned int
, because it is too large to fit in a plain int
. The &
, then, is between an unsigned int
and an int
, in which case the unsigned type wins by definition. The shift therefore happens on unsigned; thus it shifts in 0 bits from the left.
c = (0x0 | x ) >> 2;
The type of 0x0
defaults to int
because it is small enough to fit, so the bitwise or happens on ints, and so does the following shift. It is implementation defined what happens when you shift a signed integer right, but most compilers will produce an arithmetic shift that sign-extends.
Upvotes: 1