我正在寻找以下内容的无分支实现:
int f(int c) { if (c == 0) { return 0xffffffff; // all bits set } else { return c; } }
我还没有找到任何聪明的方法来做到这一点。有什么花招吗?
mfuanj7w1#
正如Nick奥德尔所提到的,编译器很有可能已经将此代码编译为没有分支的指令。一个更有可能的公式是x - (x == 0)或x - !!x,编译器通常可以通过使用CPU特定的特性来实现,而无需分支。你甚至可以尝试用一个纯粹基于位操作的公式来代替它。例如,((x - 1) & ~x) >> 31(x无符号)只有当x == 0时才是1,否则是0。所以
x - (x == 0)
x - !!x
((x - 1) & ~x) >> 31
x
x == 0
1
0
x - (((x - 1) & ~x) >> 31)
将是f的完全无分支实现。在实践中,我希望它比编译器为其他公式生成的任何东西都要慢。
f
mcvgt66p2#
你可以将c转换为bool类型,如果设置了任何一位,则得到1,否则得到0。使用_Bool或#include <stdbool.h>,除非使用C23。然后减去1。如果前一步的结果为1,则将导致-1,即二进制补码系统中的所有1位。为了使其更易于移植,您可以首先将它们转换为unsigned类型。否则,结果将为0。如果c为0,则上一步将得到一个数字,否则为0。如果数字为-1,则将数字与c进行位或运算,结果仅为-1,否则将c保持不变。
c
bool
_Bool
#include <stdbool.h>
unsigned
c | ((bool)c - 1)
2条答案
按热度按时间mfuanj7w1#
正如Nick奥德尔所提到的,编译器很有可能已经将此代码编译为没有分支的指令。一个更有可能的公式是
x - (x == 0)
或x - !!x
,编译器通常可以通过使用CPU特定的特性来实现,而无需分支。你甚至可以尝试用一个纯粹基于位操作的公式来代替它。例如,((x - 1) & ~x) >> 31
(x
无符号)只有当x == 0
时才是1
,否则是0
。所以将是
f
的完全无分支实现。在实践中,我希望它比编译器为其他公式生成的任何东西都要慢。mcvgt66p2#
你可以将
c
转换为bool
类型,如果设置了任何一位,则得到1,否则得到0。使用_Bool
或#include <stdbool.h>
,除非使用C23。然后减去1。如果前一步的结果为1,则将导致-1,即二进制补码系统中的所有1位。为了使其更易于移植,您可以首先将它们转换为
unsigned
类型。否则,结果将为0。如果
c
为0,则上一步将得到一个数字,否则为0。如果数字为-1,则将数字与c
进行位或运算,结果仅为-1,否则将c
保持不变。