Implementing Logical Right Shift in C
Solution 1
int lsr(int x, int n)
{
return (int)((unsigned int)x >> n);
}
Solution 2
This is what you need:
int logical_right_shift(int x, int n)
{
int size = sizeof(int) * 8; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << size) >> n) << 1);
}
Explain
x >> n
shifts n bits
right. However, if x
is negative, the sign bit (left-most bit) will be copied to its right, for example:
Assume every int is 32 bits here, let
x = -2147483648 (10000000 00000000 00000000 00000000)
, then
x >> 1 = -1073741824 (11000000 00000000 00000000 00000000)
x >> 2 = -536870912 (11100000 00000000 00000000 00000000)
and so on.
So we need to erase out those sign extra sign bits when n is negative.
Assume n = 5
here:
0x1 << size
moves 1
to the left-most position:
(10000000 00000000 00000000 00000000)
((0x1 << size) >> n) << 1
copies 1 to its n-1
neighbors:
(11111000 00000000 00000000 00000000)
~((0x1 << size) >> n) << 1!
reverses all bits:
(00000111 11111111 11111111 11111111)
so we finally obtain a mask to extract what really need from x >> n
:
(x >> n) & ~(((0x1 << size) >> n) << 1)
the &
operation does the trick.
And the total cost of this function is 6
operations.
Solution 3
Just store your int
in an unsigned int
, and perform >>
upon it.
(The sign is not extended or preserved if you use unsigned int)
Solution 4
I think problem is in your ">> (n-1)" part. If n is 0 then left part will be shift by -1. So,here is my solution
int logical_right_shift(int x, int n)
{
int mask = ~(-1 << n) << (32 - n);
return ~mask & ( (x >> n) | mask);
}
Solution 5
Derived from php's implementation of logical right shifting
function logical_right_shift( i , shift ) {
if( i & 2147483648 ) {
return ( i >> shift ) ^ ( 2147483648 >> ( shift - 1 ) );
}
return i >> shift;
}
For 32bit platforms only.
Related videos on Youtube
Dan
Updated on January 23, 2020Comments
-
Dan almost 3 years
I'm working on making a logical right shift function in C using only bitwise operators. Here's what I have:
int logical_right_shift(int x, int n) { int size = sizeof(int); // size of int // arithmetic shifts to create logical shift, return 1 for true return (x >> n) & ~(((x >> (size << 3) - 1) << (size << 3) -1)) >> (n-1); }
This actually works for all cases except if n = 0. I've been trying to figure out a way to fix it so it will work for n = 0 as well, but I'm stuck.
-
Ignacio Vazquez-Abrams almost 12 yearsYou're making a logical right shift operator for a signed type?
-
-
R.. GitHub STOP HELPING ICE almost 12 yearsThis is the correct answer (modulo the unnecessary and ugly cast on the result). Right-shift of a negative value has implementation-defined behavior (or is it an implementation-defined value? I forget), so any implementation of your
lsr
function in terms of using the>>
operator on a signed value is simply non-portable. -
R.. GitHub STOP HELPING ICE almost 12 yearsOne issue with this solution: strictly speaking, it has implementation-defined behavior in the case of
n==0
, since casting from anint
tounsigned
and back results in implementation defined behavior if the original value is negative. The first conversion must happen moduloUINT_MAX+1
, but the conversion back to signedint
might simply be a reinterpretation of the representation, in which case the value would be changed. -
Timothy Leung over 9 yearsI think this is correct. But can you do left shift by 32 times? That will be an undefined shift?
-
modulitos over 8 yearsYes, if
int
is, for example, 4 bytes, this fails. He needs to subtract 1 fromsize
so that ifint
is 4 bytes,size
is 31. -
Admin almost 6 yearsPlease add more information to explain your answer. Code-only answers are not well accepted here.
-
MD XF over 5 years@MarkYisri Ironic since the top voted answer on this "thread" is code-only and perfectly, clearly, answers the question.
-
M.M about 4 yearsThis causes undefined behaviour if
x >> 31
results in a non-zero value -
Jonguo almost 4 years@R.. Hi, can you give a example, or a snippet code, that can helps me to understand what you mean ? Thank you.
-
radfast almost 2 yearsIt's an elegant solution as it involve no conditional statements, therefore no CPU branching. The final
| mask
operation is unnecessary, as every bit set to 1 by that OR operation will be set to 0 by the AND operation. The mask calculation could be simplified as follows:int mask = int.MinValue >> (n - 1);
but my simplification will produce an incorrect result if n == 0, so it depends on your use case - this simplification would not be suitable for a library.