在C中设置位
我正在尝试执行以下操作:
写一个func
setbits(x,pn,y)
返回x
其中n
位从位置p
开始,设置为y
的最右边n
位,其他位保持不变?
我试过这样但没有得到正确的答案。 任何人都可以告诉我哪里错了吗?
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); }
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))
- 你
x>>()
所以你松开了x
最右边的位,然后再也没有在你的函数中恢复它们。 - 不能仅使用
&
设置位&
因为结果取决于两个操作数,除非您知道其中一个仅包含1
-
(y|(~0<
应该从 y
删除位,但这次不是 不是正确的工具,使用&
和适当的第二个操作数。
这是解决方案(我打赌有一个更短的解决方案,但这是直截了当的):
(x & ~(~(~0<
左边的部分 清除x
中的位置(位置p处的n位),右侧部分带来y
位。
捕获y的最后n位:(将是最后n位等于y的数字,其他位设置为0)
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;
而已! 没有真正测试它,但希望你能得到这个想法。