设置或重置给定位而不分支
在一次采访中,他们问我,你如何设置或重置一下? 这是一个非常简单的问题,我回答了这个问题。
之后他们问我, without branching
就做到了。 我不知道什么是分支。 我搜索了那个,我来到这里http://graphics.stanford.edu/~seander/bithacks.html
但仍然没有得到分支和非分支的概念。 请解释Branching
。
分支意味着cpu执行的指令包含条件跳转。 一个或两个选择。 这可能意味着if
, for
-loop, while
-loop, switch
, ?:
或基于布尔值作出决定的东西。
人们经常忘记的一类分支也是短路布尔运算符,并且可能(但不一定在所有CPU上)评估为真值的东西,所以int foo; ...; foo = !foo;
int foo; ...; foo = !foo;
将是某些CPU上的分支,但不是全部(不是在x86上)。
所以设置一下:
i |= (1 << bit);
重置一下:
i &= ~(1 << bit);
切换一下:
i ^= (1 << bit);
没有分支。 我实际上不知道如何使这个如此复杂,必须使用分支。
有人可能想要担心分支的原因是分支预测。 请参阅此问题和答案,以获得有关其重要性的出色解释。
可能是他们想让你展示如何编写没有分支的通用设置/重置片段…
这可以通过以下方式完成
value = (value & ~(1 << bit)) | (bitval << bit);
其中bit
是位的位置, bitval
为1表示设置,0表示复位。
甚至更一般的东西如下:
value = (value & ~(k1 << bit)) ^ (k2 << bit);
实现了几个操作:
-
k1=0
且k2=0
什么都不做 -
k1=0
且k2=1
切换该位 -
k1=1
且k2=0
清除该位 -
k1=1
且k2=1
设置该位
更普遍的
value = (value & a) ^ x;
您可以决定同时更改几位value
-
aj=0
,xj=0
→将它们设置为0 -
aj=0
,xj=1
→将它们设置为1 -
aj=1
,xj=0
→保持不变 -
aj=1
,xj=1
→翻转它们
取决于预先计算的常数a
和x
( aj
和xj
是常量中第j位的值)。
例如
value = (value & 0x0F) ^ 0x3C;
只需一次操作即可
- leave untouched bit 0 and 1 - flip bits 2 and 3 - set to 1 bits 4 and 5 - set to 0 all other bits