检查是否至少设置了一点而不跳

时间:2018-07-10 03:31:38

标签: c++ bit-manipulation

我试图找到一种有效的方法来检查整数是否为零而不跳动。

我有两个整数变量inout。如果in为零,我希望out为零。如果in不为零,我想成为一个。

如果有帮助,我知道in将为零或2的幂(仅一个置位)。我也知道,最高位和最低位都没有设置。

我可以做的很明显:out = (in == 0 ? 0 : 1);但这意味着跳伞是很昂贵的。

我可以做类似out = (in * 0xFFFFFFFF) >> 63;的事情。这意味着我要避免的乘法和移位,但是我找不到办法。也许不可能。

还有其他方法我可以不跳而只使用按位运算符和算术吗?

谢谢

3 个答案:

答案 0 :(得分:6)

这在架构上会有所不同,但是代码不会编译为在Intel CPU上的跳转。

此代码:

int square(int in) {
    int out = (in != 0);
    return out;
}

编译为:

square(int):
    xor     eax, eax
    test    edi, edi
    setne   al
    ret

或:

square, COMDAT PROC
    xor      eax, eax
    test     ecx, ecx
    setne    al
    ret      0
square ENDP

由msvc,clang和gcc与O2组成:

这只是没有优化的跳转,您将永远不会做。

答案 1 :(得分:2)

我还发现有必要这样做,将一个length-2数组索引为0(零值)和1(非零值)。

将int转换为bool,然后返回int。除了2018年之前的MSVC之外,这几乎不会在我尝试过的所有编译器(gcc,clang,最新的MSVC)上都起作用。我建议您检查汇编代码以确保在您的平台上。

int one_if_nonzero_else_zero(int value) { return (bool) value; }

编辑:这不能满足您的约束“仅使用按位运算符和算术”,但是此转换利用了程序集优化的优势,并且非常有效。

编辑:您的“显而易见”解决方案out = (in == 0 ? 0 : 1);产生的汇编代码与Jerry Jeremiah和我本人在gcc,clang和msvc上发布的解决方案相同。优化后不跳!我建议您使用它来保持清晰。

答案 2 :(得分:0)

  

我有两个整数变量inout。如果in为零,我想out为零。如果in不为零,我希望out为一。

尝试一下:

int in = ...;
int out = !!in;

Live Demo

C ++具有从intbool的隐式转换,因此当in为0时,作为bool的{​​{1}}将是false ,否则为in

然后true将是!false,而true将是!true

然后false将是!true,而false将是!false

然后,还有一个从truebool的隐式转换,因此int作为true将为1,而int将为0

因此,false为0时out为0,否则为1。