为什么这两个 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。这不 保证环绕。这被认为是溢出并且是未定义的行为。这就是为什么您会看到所看到的结果。一旦你有未定义的行为,就无法保证程序会做什么。
#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。这不 保证环绕。这被认为是溢出并且是未定义的行为。这就是为什么您会看到所看到的结果。一旦你有未定义的行为,就无法保证程序会做什么。