在C中实现逻辑右移

Dan*_*Dan 16 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);
}
Run Code Online (Sandbox Code Playgroud)

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

Ign*_*ams 29

int lsr(int x, int n)
{
  return (int)((unsigned int)x >> n);
}
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案(模数结果不必要和丑陋的演员).负值的右移有实现定义的行为(或者它是一个实现定义的值?我忘了),所以你的`lsr`函数的任何实现都是在有符号值上使用`>>`运算符的简单的不便携. (3认同)

min*_*gyc 13

这就是你需要的:

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);
}
Run Code Online (Sandbox Code Playgroud)

说明

x >> n转移n bits的权利.但是,如果x是负数,则符号位(最左边的位)将被复制到其右侧,例如:

假设每个int 在这里是32位,let
x???? =?-2147483648?(10000000 00000000 00000000 00000000),then
x?>>?1?=?-1073741824?(11000000 00000000 00000000 00000000)
x?>>?2?=?-536870912? (11100000 00000000 00000000 00000000)
等等.

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

假设n = 5在这里:

0x1 << size移到1最左边的位置:

(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)
Run Code Online (Sandbox Code Playgroud)

&操作是卓有成效的.

而这个功能的总成本是6运营.

  • 是的,如果`int`例如是4个字节,则会失败.他需要从`size`中减去1,这样如果`int`是4个字节,`size`就是31. (3认同)

Ber*_*ann 5

只需将您的存储在intunsigned int,然后对其执行>>

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

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