C否定操作员在Debian终端打印出意外的结果



这纯粹是学术的,但是我在C中创建了一个简单的真相表:

#include <stdio.h>
int main() {
  for(int j=0; j<=2; j++) {
    int bitB = (j&1);
    printf("~%d = %dn", bitB, ~bitB);
  }
  return 0;
}

终端运行:

~1 = -2
~0 = -1

通过在printf上设置休息在GDB中调试,但是我期望的是:

(gdb) print bitB
$5 = 1
(gdb) cont
Continuing.
~1 = -2
(gdb) x/xw &bitB
0xbffff3d8: 0x00000000

为什么程序输出显示负数?

这是一个完美的预期结果,至少在两者补充系统中表示负数的系统上:

  • 负面的所有位都设置为1
  • 负两个位将所有位设置为1,除了最后一个位。

因此,翻转所有的零位会产生 -1,然后翻转所有 1的位 -2

0000000000000000 -> 1111111111111111 // Zero becomes negative 1
0000000000000001 -> 1111111111111110 // One becomes negative 2

数学上,要在两个补充表示中翻转一个数字的符号,您可以翻转数字的所有位,然后将1添加到结果中。只需翻转所有x的所有位即可产生-x-1。这正是您看到的结果。

为什么程序输出显示负数?

因为您将签名的int%d格式指定符一起使用,而打印的位模式恰好是负数的表示。

在所有系统和数字表示上,这都会给出负数。您正在补充所有位,包括符号位。

因为您使用类型int(包含其符号(,并且反相最高的位也根据两个补充规则更改标志(请注意~反转/补充所有位(。

如果您期望~为您提供没有符号的表示形式,则可能要使用unsigned int(和%u(。

最新更新