C位循环移位-意外结果
我目前正在进行K&R C书籍练习,正在进行第2章的练习8。挑战在于编写一个函数“rotright”,将无符号整数x的位旋转(或圆移位)n位。我相信我已经想出了一个解决方案,但它并没有返回我所期望的结果。给定二进制数字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
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,作为一般规则,是的,最好避免在按位操作中使用有符号的数据类型。