写一个函数setbit(x,p,n,y),它返回x,从p位置开始的n位设置为y的最右边的n位,其他位保持不变
我搞不清我做错了什么。
#include <stdio.h>
unsigned setbits(unsigned int x, int p, int n, unsigned y);
int main()
{
unsigned x = 213;
unsigned y = 121;
int p = 4;
int n = 4;
x = setbits(x, p, n, y);
printf("%u\n", x);
getch();
return 0;
}
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
return ((~(~0 << n) & y) << (p + 1 - n) | (~(~(~0 << n)) << (p + 1 - n) & x));
}
从理论上讲,我得到了211,但是我的代码产生了210。K&R答案簿算法也返回210。我搞不清我在这里做错了什么。
编辑:这是答案本上的代码:
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
return x & ~(~(~0 << n) << (p + 1 - n)) | (y & ~(~0 << n)) << (p + 1 - n);
}
重新编辑。我在把代码分成几行的时候想出来了。问题是最后一个x旁边的括号放错了:
//original
{
return ((~(~0 << n) & y) << (p + 1 - n) | (~(~(~0 << n)) << (p + 1 - n) & x));
}
//fixed
{
return ((~(~0 << n) & y) << (p + 1 - n)) | (~(~(~0 << n) << (p + 1 - n)) & x);
}
这是被破解的密码。这看起来还不好吗?我是否应该使用这样的变量:
int setbits(unsigned x, int p, int n, unsigned y)
{
unsigned z, k;
z = y & ~(~0 << n);
z = z << (p + 1 - n);
k = ~((~(~0 << n)) << (p + 1 - n));
k = k & x;
return z | k;
}
最佳答案
措辞有点难理解,但我认为这正是它所要求的:
unsigned setbits(unsigned int x, int p, int n, unsigned y){
return x | ((y&((1<<n)-1))<<(p-n));
}
unsigned setbits(unsigned int x, int p, int n, unsigned y){
return (x & ~(((1<<n)-1)<<(p-n))) | ((y&((1<<n)-1))<<(p-n));
}
故障:
左半部分|
((1<<n)-1)
将向左移动1n位,减去1将使所有位向右移动1。<<(p-n)
按p-n左移~
将它们反转,将这些位保留为0,其他位保留为1x &
将这些位转换为0。右半部分|
x
同上((1<<n)-1)
将仅屏蔽这些位y &
将把这些位p-n移到左边<<(p-n)
将或这些值放在一起,以便:从
left | right
位置开始的n
位被设置为p
的最右边的n
位,保持y
的其他位不变