“写一个函数setbits(x,p,n,y)返回x,其中n位从位置p开始,设置为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&amp; 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;
}
答案 0 :(得分:0)
措辞有点难以理解,但我认为这就是它所要求的:
<击> 撞击>
<击>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)
将向左移1 n位,减1使所有位向右移1。<<(p-n)
将它们左移p-n ~
将这些位置为0,其他所有位置为1s x &
并将其x
转换为0。|
的右半部分((1<<n)-1)
与上述相同y &
将仅屏蔽那些位<<(p-n)
会将这些位p-n移到左侧left | right
将值组合在一起,以便:
n
开始的p
位设置为n
的最右侧y
位,而x
的其他位保持不变答案 1 :(得分:0)
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
return x & ~(~(~0 << n) << (p + 1 - n)) | (y & ~(~0 << n)) << (p + 1 - n);
}
p=4
x
组件 l1 = ~0 => 1111_1111_1111_1111_1111_1111_1111_1111
l2 = l1 << n => 1111_1111_1111_1111_1111_1111_1111_0000
l3 = ~(l2) => 0000_0000_0000_0000_0000_0000_0000_1111
l4 = (p + 1 - n) => 1
l5 = (l3) << (l4) => 0000_0000_0000_0000_0000_0000_0001_1110
l6 = ~l5 => 1111_1111_1111_1111_1111_1111_1110_0001
l7 = x & l6 => xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxx0_000x
y
组件 s1 = ~0 => 1111_1111_1111_1111_1111_1111_1111_1111
s2 = s1 << n => 1111_1111_1111_1111_1111_1111_1111_0000
s3 = ~s2 => 0000_0000_0000_0000_0000_0000_0000_1111
s4 = (p + 1 - n) => 1
s5 = s3 << s4 => 0000_0000_0000_0000_0000_0000_0001_1110
s6 = y & s5 => 0000_0000_0000_0000_0000_0000_000y_yyy0
o = l7 | s6
xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxy_yyyx
^all these uncounted bits!!!^ .
编写一个函数setbits(x,p,n,y),该函数返回x,其中n位从位置p开始的n位设置为最右 ,其他位保持不变。
我们是否从零开始从右边开始计数,然后到达位置p
时开始从右边的n
位开始计数?
unsigned
类型为int
,可以通过
$ gcc -o ansi-c_2-6 *.c -std=c89
$ ansi-c_2-6
#include <stdio.h>
int main() {
printf("%s", (sizeof(unsigned) == sizeof(int)) ? "TRUE" : "FALSE");
return 0;
}
解决方案书有误。
注释
bits = CHAR_BIT * sizeof(
数据类型 ))
INT_MIN >> 31 == ~0
if p + n > 32
,您可以放弃,但很快就会失去控制x
的东西 left_mask = INT_MIN >> (p - 1)
right_mask = INT_MAX >> (p - 1 + n)
x = x & (left_mask | right_mask)
y
的东西 mid_mask = ~(left_mask | right_mask)
y = (y << (bits - p - n)) & mid_mask
return
的东西 x | y
改为执行此操作
unsigned setbits(unsigned x, unsigned char p, unsigned char n, unsigned y)
{
char bits = CHAR_BIT * sizeof(unsigned);
unsigned left_mask, right_mask, mid_mask;
left_mask = p > 0 ? INT_MIN >> (p-1) : 0;
right_mask = INT_MAX >> (p - 1 + n);
mid_mask = (left_mask | right_mask) & x;
x = (left_mask | right_mask) & x;
y = y << (bits - p - n) & mid_mask;
return x | y;
}
限制:
n > 0
p + n < sizeof(unsigned) * CHAR_BIT
答案 2 :(得分:-1)
unsigned setbits(unsigned x, int p, int n, int y) {
return x | (~(~0 << n) << p);
}