为什么下面的C代码不能为负数返回-1,为0返回0,为正数返回1?
(((x >> 31) ^ -1) + 1) | (!x ^ 1);具体地说,当我传入负数时,它返回1。似乎如果我有一个负数(即31位移位后最低有效位是1),用-1 XORing它将得到-2 (即所有1和最低有效位位置的0),加1将使其为-1。
发布于 2013-04-22 23:02:01
根据C99标准,如果x为负,则x >> n的结果是由实现定义的。所以你有问题的原因取决于你的编译器和架构。
然而,最有可能的是,当你移位x时,它是符号扩展的,也就是说,最高位被重复以保持符号与操作数相同。这就是我的编译器所发生的事情。所以对于任何负数,x >> 31都是-1。另外,对于任何非零数,!x都是0(即false)。假设x是32位整数,这是适用的。如果您将x设为无符号整型,则它应该可以工作,但请考虑以下替代方案:
(x < 0) ? -1 : ((x > 0) ? 1 : 0)我认为这不是那么神秘。
这是一个程序,您可以使用它来查看您的表达式正在做什么
#include <stdio.h>
#define EVALUATE(x) printf("%s = %d\n", #x, x)
int main(int argc, char** argv)
{
unsigned int x = 51;
EVALUATE(x >> 31);
EVALUATE(((x >> 31) ^ -1));
EVALUATE(((x >> 31) ^ -1) + 1);
EVALUATE(!x);
EVALUATE(!x ^ 1);
EVALUATE((((x >> 31) ^ -1) + 1) | (!x ^ 1));
return 0;
}发布于 2013-04-22 22:16:02
>>通常会对带符号的数据进行算术移位,所以((-1) >> 31) == (-1),与您的假设相反。正如其他人指出的那样,该标准不能保证这一点,但在现代系统中很可能是这样的。在任何情况下,都要小心这种类型的位摆动。如果可移植性是一个问题,或者速度不是问题,那么您应该用不同的方式来完成它。有关一些想法,请参阅Is there a standard sign function (signum, sgn) in C/C++?。
https://stackoverflow.com/questions/16149277
复制相似问题