为什么这两个 C 语句产生相同的输出

Why do both of these C statements produce same outputs

#include<stdio.h>
int main() {
     int x = 0x80000000;
     printf("%i\n",(((x - 1) >> 31) & 1));  //shows 0 as output
     printf("%i\n",!(((x - 1) >> 31) & 1));  //shows 0 as output(expected 1)
}

为什么会这样?因为这两个语句执行相同的操作,除了 !操作员。为什么第二个 printf 不输出 1? 据我所知,逻辑不超过 0 给出 1,逻辑不超过其他数字给出 0。我在这里做错了吗?

您在这里看到的是由有符号整数溢出引起的 undefined behavior 的表现。

假设一个32字节int使用二进制补码,值0x80000000超出了int的范围,因此它进行了implementation-defined转换。最有可能的是,它会转换为值 -2147483648,这是您系统上 int 中可以保存的最小值。

在这两种情况下,接下来要做的就是从该值中减去 1。这 保证环绕。这被认为是溢出并且是未定义的行为。这就是为什么您会看到所看到的结果。一旦你有未定义的行为,就无法保证程序会做什么。