Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C位循环移位-意外结果_C_Bit Manipulation_Bitwise Operators - Fatal编程技术网

C位循环移位-意外结果

C位循环移位-意外结果,c,bit-manipulation,bitwise-operators,C,Bit Manipulation,Bitwise Operators,我目前正在进行K&R C书籍练习,正在进行第2章的练习8。挑战在于编写一个函数“rotright”,将无符号整数x的位旋转(或圆移位)n位。我相信我已经想出了一个解决方案,但它并没有返回我所期望的结果。给定二进制数字213,即11010101,向右旋转2位将产生0111011,即117。然而,我的程序在被给予x=213和n=2时返回53。我试着在注释中以二进制形式写出整数的处理过程,但没有发现问题。任何帮助都将不胜感激 #include <stdio.h> unsigned rot

我目前正在进行K&R C书籍练习,正在进行第2章的练习8。挑战在于编写一个函数“rotright”,将无符号整数x的位旋转(或圆移位)n位。我相信我已经想出了一个解决方案,但它并没有返回我所期望的结果。给定二进制数字
213
,即
11010101
,向右旋转
2
位将产生
0111011
,即
117
。然而,我的程序在被给予
x=213
n=2
时返回
53
。我试着在注释中以二进制形式写出整数的处理过程,但没有发现问题。任何帮助都将不胜感激

#include <stdio.h>

unsigned rotright(unsigned x, int n)
{
    /* Example with x = 11010101 (213 in decimal), n = 2
        First iteration:
            x = (01101010) | ~(11111111 >> 1) = 11101010
        Second iteration:
            x = (01110101) | ~(11111111 >> 0) = 01110101
        Returns 01110101

    right shifts only if last bit of x == 1, then sets first bit of right shifted x to 1
    if last bit of x == 0, x is right shifted by 1 and then unchanged.

    (01101010) | ~(11111111 >> (11010101 & 00000001))
    = 01101010 | ~(11111111 >> 00000001)
    = 01101010 | 10000000 = 11101010

    (11101010) | ~(11111111 >> (11101010 & 00000001))
    = 01110101 | ~(11111111 >> 0)
    = 01110101 | 00000000 = 01110101
    */
    for (; n > 0; n--)
        x = (x >> 1) | ~(~0 >> (x & 1));
    return x;
}

int main()
{
    printf("%d\n", rotright(213, 2));
    return 0; 
}
#包括
无符号rotright(无符号x,int n)
{
/*示例x=11010101(十进制213),n=2
第一次迭代:
x=(011010)|~(11111111>>1)=11101010
第二次迭代:
x=(0111011)|~(11111111>>0)=01110101
返回0111011
仅当x的最后一位==1时右移,然后将右移x的第一位设置为1
如果x的最后一位=0,则x右移1,然后保持不变。
(01101010) | ~(11111111 >> (11010101 & 00000001))
= 01101010 | ~(11111111 >> 00000001)
= 01101010 | 10000000 = 11101010
(11101010) | ~(11111111 >> (11101010 & 00000001))
= 01110101 | ~(11111111 >> 0)
= 01110101 | 00000000 = 01110101
*/
对于(;n>0;n--)
x=(x>>1)| ~(~0>>(x&1));
返回x;
}
int main()
{
printf(“%d\n”,rotright(213,2));
返回0;
}
x=(x>>1)| ~(~0>>(x&1))

你得到53,因为这是(213>>2)

~(~0>>(x&1))
始终为0,因为在您的例子中~0是-1,-1>>n再次是-1,最后-1是0


你想要的是:

#include <stdio.h>
#include <limits.h>

unsigned rotright(unsigned x, int n)
{
   unsigned mask = (1u << (CHAR_BIT * sizeof(int) - 1));

  for (; n > 0; n--) {
    x = (x / 2) | ((x & 1) ? mask : 0);
  }
  return x;
}

int main()
{
    printf("%d\n", rotright(213, 2));
    return 0; 
}
#包括
#包括
无符号rotright(无符号x,int n)
{
无符号掩码=(1u 0;n--){
x=(x/2)|((x&1)掩模:0);
}
返回x;
}
int main()
{
printf(“%d\n”,rotright(213,2));
返回0;
}

在32位上,结果是1073741877为10000000000000000110101,而不是117,假设您在8位上工作。。。而
~0
-1
,因为常量
0
的类型是
int
。切换到无符号整数与使用
0u
一样简单。此外,右移负值的效果不一定是算术移位,例如,我同意OP似乎观察到的。它是实现定义的,因此它可能是OP预期的逻辑转变,甚至是其他东西。@JohnBollinger这就是为什么我在你的案例中说谢谢你的回答。我忘了右移符号值是唯一的。出于这个原因,您是否建议我以后避免这样做,这样我就知道会发生什么?@muke除以2而不是>>1以确定result@muke,作为一般规则,是的,最好避免在按位操作中使用有符号的数据类型。