我目前正在研究K&R C书的练习,并且正在第2章的练习8上。挑战在于编写一个函数“ rotright”,该函数将无符号整数x的位旋转(或循环移位)n位。我相信我已经提出了一个解决方案,但是它并没有返回我期望的结果。给定数字213
,它是二进制数11010101
,向右旋转2
位将产生01110101
,即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;
}
答案 0 :(得分:3)
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;
}
在32位上,结果是1073741877是1000000000000000000000000110101,而不是117(假设您在8位上工作)