c - 位运算 - 表示有符号整数的符号

标签 c binary bit-manipulation

为什么以下 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/

相关文章:

c - 如何通过终端将段落读取为 C 中的单个字符串?

c - 解决快速搜索算法分配的技巧

c# - 如何测试按位枚举是否包含 C# 中另一个按位枚举的任何值?

c - 更优雅的多位移位解决方案

c - SO_KEEPALIVE 和轮询

c - 如何让用户创建一个函数? [ 图书馆 ? ]

c++ - std::cout 如何将数字类型转换为基数 10?

java - 保留一组星期几

python - SWIG:如何使用 %apply 返回结构? 'No typemaps defined' 警告

ios - 否 在新的 iTunes Connect 10/09 中拒绝此二进制链接