整数及其负数的按位OR的目的

时间:2014-09-18 06:04:20

标签: c integer bitwise-or

我很好奇NaN在IEEE单精度和双精度浮点中的实现和表示,我发现{是3N}的“是NaN”函数。即:

int isnan(double x)
{
    int32_t hx,lx;

    // Move lower 32 bits of double to lx, higher 32 to hx.
    EXTRACT_WORDS(hx,lx,x);

    // Remove sign bit, since -NaN and NaN are both NaN.
    hx &= 0x7fffffff;

    // Equivalent to hx |= (lx != 0).
    hx |= (u_int32_t)(lx|(-lx))>>31;

    // Difference is negative iff (hx & 0x7ff00000) == 0x7ff00000 and (hx & 0x000fffff) != 0.
    hx = 0x7ff00000 - hx;
    return (int)((u_int32_t)(hx))>>31;
}

我不理解(lx|(-lx)) >> 31的目的,并且在我未能在我的脑海中推理出来之后,我在所有整数上测试了它,发现lx = 0的结果为0,否则为1

我能想到的唯一原因是,由于某些C标准未定义为真实操作分配的整数值(例如,不保证为1表示真实),或许使用(lx != 0)代替不可能或许!=比负位移位慢。否则,我很难过。

作为参考,我用以尝试所有整数的代码,如果有错误。

#include <stdio.h>
#include <stdint.h>
int main(void) {
        int32_t i = 0;
        do {
                if (((uint32_t)(i | (-i)) >> 31) == 0)
                        printf("%d\n", i); // prints only 0
        } while (i++ != 0xFFFFFFFF); // overflows to -max_int and then climb to -1
        return 0;
}

1 个答案:

答案 0 :(得分:3)

表达式(u_int32_t)(lx|(-lx))>>31相当于lx==0? 0:1

但是,对于lx==0? 0:1,您要对目标代码强制执行分支操作。

与一些按位操作相比,这可能会降低性能。

这实际上取决于底层的HW架构以及手头的指定编译器。

但它肯定会导致不一致的性能,具体取决于分支预测启发式。

(u_int32_t)(lx|(-lx))>>31的运行时间保证在每次执行时都相同。