返回x,其中n位从位置p开始,设置为y的最右边n位,其他位保持不变

时间:2011-07-17 23:00:29

标签: c implementation bit-manipulation

我的解决方案

get the rightmost n bits of y
a = ~(~0 << n) & y

clean the n bits of x beginning from p
c = ( ~0 << p | ~(~0 << (p-n+1))) & x

set the cleaned n bits to the n rightmost bits of y
c | (a << (p-n+1))

这是一个相当长的陈述。我们有更好的吗?

 i.e
x = 0 1 1 1 0 1 1 0 1 1 1 0
p = 4
y = 0 1 0 1 1 0 1 0 1 0 
n = 3

the 3 rightmost bits of y is 0 1 0 
it will replace x from bits 4 to bits 2 which is 1 1 1

3 个答案:

答案 0 :(得分:1)

我写了类似的一篇:

 unsigned setbits (unsigned x, int p, int n, unsigned y)
{
  return (x & ~(~(~0<<n)<<(p+1-n)))|((y & ~(~0<<n))<<(p+1-n));
}

答案 1 :(得分:0)

有两种合理的方法。

一个是你的:抓取y的低n位,核对x的中间n位,然后“或”将它们放到位。

另一个是从三个部分构建答案:低位“或”中间位“或”高位。

我认为我真的更喜欢你的版本,因为我打赌np更可能是编译时常量而不是xy。所以你的答案变成了两个使用常数和一个“或”的掩蔽操作;我怀疑你会做得更好。

我可能会略微修改它以便于阅读:

mask = (~0 << p | ~(~0 << (p-n+1)))
result = (mask & a) | (~mask & (y << (p-n+1)))

...但是当mask是常量时,这与你的速度(实际上是代码)相同,而当mask是变量时,速度可能会慢一些。

最后,请确保您有充分的理由担心这一点。干净的代码是好的,但对于这么短的东西,把它放在一个记录良好的函数中,并没有那么重要。快速代码很好,但在您的分析器告诉您之前,不要尝试微观优化这样的东西。 (现代CPU可以非常快速地完成这些工作;应用程序的性能不太可能受到这种功能的限制。至少在被证明有罪之前它是“无辜的”。)

答案 2 :(得分:0)

看看下面的描述性代码:

int setbitsKR(int x, int p, int n, int y){
    int shiftingDistance = p - n + 1,
        bitmask = (1 << n) - 1, // example, 11
        digitsOfY = (y & bitmask) << shiftingDistance, // whatever        
        bitmaskShiftedToLeft = bitmask << shiftingDistance, // 001100
        invertedBitmaskShiftedToLeft = ~bitmaskShiftedToLeft; // 110011

    // erase those middle bits of x
    x &= invertedBitmaskShiftedToLeft;

    // add those bits from y into x
    x |= digitsOfY;

    return x;
}

简而言之,它将创建一个位掩码(1的字符串),将其移位到x的中间位置,将x的那些位加{{1} } &(反向位掩码)的字符串,最后0的位置是|的正确数字。