5

我正在尝试执行以下操作:

编写一个函数setbits(x,p.n,y),返回从设置为最右边位的位置开始x的位,而其他位保持不变?npny

我像这样尝试过,但没有得到正确的答案。谁能告诉我哪里错了?

unsigned setbits(unsigned x,int p,int n,unsigned y)
{
    return (x>>p & (y|(~0<<n)));
}
4

4 回答 4

3

就像是:

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);
}
于 2012-07-21T08:38:59.280 回答
1
  1. x>>()因此松开了x最右边的位,然后在以后的功能中永远不会恢复它们。
  2. 不能仅使用设置位,&因为结果取决于两个操作数,除非您知道其中一个仅包含1
  3. (y|(~0<<n))应该削减位,y但事实并非如此,这一次|不是正确的工具,使用&和适当的第二个操作数。

这是解决方案(我敢打赌有一个更短的,但这是直截了当的):

(x & ~(~(~0<<n)<<p) | (y&~(~0<<n)) << p);

左侧部分|清除x(位置 p 处的 n 位)中的位置,右侧部分带来y位。

于 2012-07-21T08:48:24.493 回答
1

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

于 2012-07-21T08:32:48.033 回答
1

捕获 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;

而已!没有真正测试它,但希望你能明白。

于 2012-07-21T08:43:19.917 回答