为什么以下 C 代码不能为负数返回 -1,为 0 返回 0,为正数返回 1?
(((x >> 31) ^ -1) + 1) | (!x ^ 1);
具体来说,当我传入负数时,它返回 1。看起来如果我有一个负数,虽然(即最低有效位在 31 位移位后是 1),与 -1 进行异或运算会给我 -2(即所有 1 和最低有效位位置的 0),加 1 会使它成为 -1。
最佳答案
根据 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;
}
关于c - 位运算 - 表示有符号整数的符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16149277/