在序数中设置位范围

时间:2012-03-25 14:21:10

标签: c bit-manipulation

Following my previous question,我需要创建一个由固定比特数设置为1的值。我使用了以下函数:

void MaskAddRange(UINT& mask, UINT first, UINT count)
{
    mask |= ((1 << count) - 1) << first;
}

但是,正如发现的那样,count = 32无效。 1 << count在这种情况下理论上的结果是未定义的行为(或结果),而实际上在x86上是1,因为移位操作数被模数为32。

我想修复此表达式以便在这种极端情况下正常工作。什么是最简单/最好/最有效的方法?

通过分支(if?)处理这个特定情况有点简单,虽然很难看,但我敢打赌它效率也很低。

另一种方法是将移位操作数提升为更大的类型(64位)。我的意思是:

void MaskAddRange(UINT& mask, UINT first, UINT count)
{
    mask |= (UINT(unsigned __int64(1) << count) - 1) << first;
}

有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

除非你能证明,否则永远不要认为任何事情是无效的。 if-else可能在您的架构+操作系统上比升级到64位更高效。我认为除了你已发布的那两种方法之外,还没有任何其他理智的方法。

我会选择if-else,因为记录处理极端情况的意图。提升到64位并不表示意图。

答案 1 :(得分:0)

您可以使用

mask |= (UINT(-1)<<first) & (UINT(-1)>>(32-first-count))

哪个更复杂但在任何情况下都应该有效。该表达式相对于其他解决方案的效率可能取决于架构和编译器。