在C中实现逻辑右移

时间:2011-03-09 22:42:01

标签: c bit-manipulation

我正在使用仅按位运算符在C中创建逻辑右移位函数。这就是我所拥有的:

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);
}

这实际上适用于所有情况,除非n = 0.我一直试图找到一种方法来解决它,所以它也适用于n = 0,但我被卡住了。

8 个答案:

答案 0 :(得分:28)

int lsr(int x, int n)
{
  return (int)((unsigned int)x >> n);
}

答案 1 :(得分:12)

这就是你需要的:

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);
}

<强>解释

x >> nn bits改为正确。但是,如果x为负数,则符号位(最左侧位)将复制到其右侧,例如:

假设每个int 32位,让
x     = -2147483648 (10000000 00000000 00000000 00000000),然后是 x >> 1 = -1073741824 (11000000 00000000 00000000 00000000)
x >> 2 = -536870912  (11100000 00000000 00000000 00000000)
等等。

因此,当n为负时,我们需要删除那些符号额外符号位。

在此假设n = 5

0x1 << size1移至最左侧位置:

(10000000 00000000 00000000 00000000)

((0x1 << size) >> n) << 1将1复制到其n-1个邻居:

(11111000 00000000 00000000 00000000)

~((0x1 << size) >> n) << 1!反转所有位:

(00000111 11111111 11111111 11111111)

所以我们最终获得了一个掩码来从x >> n中提取真正需要的东西:

(x >> n) & ~(((0x1 << size) >> n) << 1)

&操作可以解决问题。

此功能的总费用为6次操作。

答案 2 :(得分:3)

只需将int存储在unsigned int中,然后执行>>

(如果使用unsigned int,则不会扩展或保留符号)

  

http://en.wikipedia.org/wiki/Logical_shift

答案 3 :(得分:2)

我认为问题出在你的“&gt;&gt;(n-1)”部分。如果n为0,则左侧部分将移位-1。 所以,这是我的解决方案

int logical_right_shift(int x, int n)
{
  int mask = ~(-1 << n) << (32 - n);
  return  ~mask & ( (x >> n) | mask); 
}

答案 4 :(得分:1)

派生自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;
}

仅限32位平台。

答案 5 :(得分:0)

与@ Ignacio的评论一样,我不知道你为什么要这样做(不像其他答案那样只对unsigned进行演员),但是(假设有两个补码和二进制,并且签名班次是算术的:

(x >> n) + ((1 << (sizeof(int) * CHAR_BIT - n - 1)) << 1)

或:

(x >> n) ^ ((INT_MIN >> n) << 1)

答案 6 :(得分:0)

Milnex的答案很棒并且有一个很棒的解释,但遗憾的是,由于总体规模的变化,实施失败了。这是一个工作版本:

int logicalShift(int x, int n) {
  int totalBitsMinusOne = (sizeof(int) * 8) - 1; // usually sizeof(int) is 4 bytes (32 bits)
  return (x >> n) & ~(((0x1 << totalBitsMinusOne) >> n) << 1);
}

要将1作为最高位,并将其他所有零置于其他位置,我们需要将0x1移至number of bits - 1。我正在提交自己的答案,因为我对已接受答案的编辑被某种方式拒绝了。

答案 7 :(得分:0)

{{1}}

仅适用于32位