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

我很好奇NaN在IEEE单精度和双精度浮点中的实现和表示,我发现这是“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|(-lx)) >> 31没有推理出来后,我在所有整数上测试了它,发现它对于lx = 0和1导致0除此以外。

我能想出的唯一原因是,可能使用(lx != 0)而不是因为某些C标准没有定义为真实操作分配了什么整数值(例如,不能保证1为真)或者也许!=比负位移位慢。 否则,我很难过。

作为参考,我用来尝试所有整数的代码,以防出错。

 #include  #include  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; } 

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

但是, lx==0? 0:1 lx==0? 0:1 ,您在对象代码中强制执行分支操作。

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

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

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

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