我正在尝试执行以下操作:
编写一个函数
setbits(x,p.n,y)
,返回从设置为最右边位的位置开始x
的位,而其他位保持不变?n
p
n
y
我像这样尝试过,但没有得到正确的答案。谁能告诉我哪里错了?
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
return (x>>p & (y|(~0<<n)));
}
就像是:
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
unsigned mask = (1U << n) - 1U; // n-bits
y &= mask; // rightmost n bits of y
y <<= p; // which begin at position p
mask <<= p; //idem
x &= ~mask; //set the 0s
x |= y; //set the 1s
return x;
}
或者,如果你想用更少的行来完成它,更难调试,但更酷:
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
unsigned mask = (1U << n) - 1U; // n-bits
return (x & ~(mask << p)) | ((y & mask) << p);
}
x>>()
因此松开了x
最右边的位,然后在以后的功能中永远不会恢复它们。 &
因为结果取决于两个操作数,除非您知道其中一个仅包含1
(y|(~0<<n))
应该削减位,y
但事实并非如此,这一次|
不是正确的工具,使用&
和适当的第二个操作数。这是解决方案(我敢打赌有一个更短的,但这是直截了当的):
(x & ~(~(~0<<n)<<p) | (y&~(~0<<n)) << p);
左侧部分|
清除x
(位置 p 处的 n 位)中的位置,右侧部分带来y
位。
Kernighan 和 Ritchie,第 2 版,练习 2-6。解决方案来自http://users.powernet.co.uk/eton/kandr2/krx206.html:
(x & ((~0 << (p + 1)) | (~(~0 << (p + 1 - n))))) | ((y & ~(~0 << n)) << (p + 1 - n))
捕获 y 的最后 n 位:(将是最后 n 位等于 y 的数字,其他设置为零)
last_n_bits_of_y = y & (((1<<(n+1))-1);
然后我们可以通过 (32-n-p+1) 来抵消它(检查这个!)
last_n_bits_of_y_offset = last_n_bits_of_y << (32-n-p+1);
现在我们擦除 x 我们想要更改的位:
new_x = x & (~( (((1<<(n+1))-1) << (32-n-p+1) ) );
并用我们的位填充它:
new_x = new_x & last_n_bits_of_y_offset;
而已!没有真正测试它,但希望你能明白。