在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))

  1. x>>()所以你松开了x最右边的位,然后再也没有在你的函数中恢复它们。
  2. 不能仅使用&设置位&因为结果取决于两个操作数,除非您知道其中一个仅包含1
  3. (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; 

而已! 没有真正测试它,但希望你能得到这个想法。