代码之家  ›  专栏  ›  技术社区  ›  Mathieu Pagé

检查是否至少设置了一点而没有跳跃

  •  2
  • Mathieu Pagé  · 技术社区  · 8 年前

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

    我有两个整数变量 in out 是的。如果 在里面 是零,我想要 外面的 为零。如果 在里面 不是零,我想成为一个。

    如果可以的话,我知道 在里面 将为0或2的幂(仅一个设置位)。我也知道,最重要和不重要的位永远不会被设置。

    我可以做显而易见的事: out = (in == 0 ? 0 : 1); 但这意味着一个代价高昂的跳跃。

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

    有没有其他方法可以做到这一点,而不跳,只使用位运算符和算术?

    谢谢

    3 回复  |  直到 8 年前
        1
  •  6
  •   Jerry Jeremiah    8 年前

    这与体系结构不同,但是代码 编译到英特尔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:

    这只是一个没有优化的跳跃,无论如何你都不会做。

        2
  •  2
  •   Taylor Nichols    8 年前

    我还发现需要这样做,将length-2数组索引为0表示零值,1表示非零值。

    将int强制转换为bool,然后再返回int。这不会跳到我尝试过的几乎所有编译器(gcc、clang、最近的msvc)上,除了2018年之前的msvc。我建议您检查程序集代码以确保在您的平台上。

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

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

    编辑:你的“显而易见”的解决方案 out = (in == 0 ? 0 : 1); 结果生成了与jerry jeremiah和我在gcc、clang和msvc上发布的解决方案相同的汇编代码。优化后不跳!我建议你用它来解释清楚。

        3
  •  0
  •   Remy Lebeau    8 年前

    我有两个整数变量 in out 是的。如果 在里面 是零,我想要 外面的 为零。如果 在里面 不是零,我想要 外面的 成为一个。

    试试这个:

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

    Live Demo

    C++有一个隐式转换定义为 int bool 如此 在里面 作为一个 布尔 false 什么时候 在里面 是0,将是 true 否则。

    那么 !false 真的 ,和 !true 是的。

    那么 啊!真的 ,和 啊!假 是的。

    然后还有一个隐式转换定义自 布尔 内景 如此 真的 作为 内景 将是1,并且 将为0。

    因此, 外面的 将在0时 在里面 为0,否则为1。