C中位的正确旋转

我正在 K&R 中进行练习 2-8,它要求我们编写函数rightrot(int x, int n),使得 的所有位x都向右移动 n 次,而从右端掉下来的位重新出现在左端。

这是我尝试的解决方案,我将每一位一位一位地移动:

int rightrot(int x, int n)
{
    int i, rmb;

    for(i = 0; i < n; ++i)
    {
        // get right-most bit
        rmb = x & 1;

        // shift 1 to right
        x = x >> 1;

        // if right-most bit is set, set left-most bit
        if (rmb == 1)
            x = x | (~0 ^ (~0 >> 1) );
    }

    return x;
}

当我执行时rightrot(122, 2),我希望得到94因为122is111101094is 1011110。相反,我知道30哪个恰好是0011110. 显然,我设置最左边位的方法并没有像我期望的那样工作。有没有人发现明显的错误?我只是在学习捕获位等。

注意:我从这篇文章中获得了设置最左边位的技术。

回答

我们来分析一下(~0 ^ (~0 >> 1) )

~0is 又-1
~0 >> 1-1,如果符号位是1右移将用1s填充新位。
-1 ^ -10
x = x | 0x

解决方案是,如果您想进行位操作,您应该使用无符号数据类型。

所以你应该使用行x = x | (~0u ^ (~0u >> 1) );
来避免其他问题,参数x也应该是unsigned int.

https://ideone.com/7zPTQk

  • *`~0 >> 1` is again `-1`,* Note that is [implementation-defined](https://port70.net/~nsz/c/c11/n1570.html#6.5.7p5).

以上是C中位的正确旋转的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>