优化" i = b? (i | mask):( i&〜mask)"

时间:2016-11-16 10:34:38

标签: c bit-manipulation ternary-operator

我希望能够设置或清除uintX_t t的多个位。

i是一个运行时变量(uintX_t)。 b是一个运行时变量(uintX_t),它被约束为01

mask是编译时常量。

有没有比以下更好的方式:

i = b ? (i | mask) : (i & ~mask)

我希望避免分支,如果可能的话。如果重要的话,Target就是ARM。

4 个答案:

答案 0 :(得分:6)

利用-1u是设置了所有位的值的事实:

i = (i & ~mask) | (mask & -b);

i ^= (i ^ -b) & mask;

第二种方法减少了操作次数和代码大小。第一种方法在超标量体系结构上可能仍然更快,因为某些操作可以并行执行。

答案 1 :(得分:5)

这里的想法是用乘法替换分支,我们可以根据b的值将每一边归零:

i = (i | (mask * b)) & (~mask | (mask * b));

答案 2 :(得分:5)

另一种选择:始终将位设置为0(左侧部分),并可选择将位设置为1(右侧部分)。

i = (i & ~mask) | (mask * b);

答案 3 :(得分:1)

最可读的方法是通过几个步骤完成此操作 - 这样做不会影响性能,但会提高可读性。

与逐位运算符一样,您必须小心隐式类型提升。例如,不小心使用~往往会产生隐含的促销错误。 (?:运算符还通过平衡第二个和第三个操作数来静默地提升结果。)

可读,便携,安全的代码:

uintx_t i = ... ;
uintx_t b = ... ;  // 1 or 0

i &= (uintx_t)~mask;   // always clear the bit
i |= mask * b;         // if b is 1, set the bit, otherwise OR with 0