Binary 按位运算符,为什么对已应用NOT运算符的二进制数加1会使其为负数而不是另一个数?

Binary 按位运算符,为什么对已应用NOT运算符的二进制数加1会使其为负数而不是另一个数?,binary,bit-manipulation,Binary,Bit Manipulation,我刚刚开始学习位运算符(尽管我很难找到任何绝对的初学者资源)。我理解二进制文件的工作原理和读取方法,但我不理解以下内容 如果您使用二进制数字37: 00100101并对其应用~(NOT)运算符,位被翻转到 11010 在我正在阅读的教程中,它说你必须添加一个1作为一种标志,以表示它是负的。因此它变成了11011011。我不明白为什么这个新数字不被读为219 在一个相关的注释中,是否有人有任何深度,解释我可以使用的所有资源,以真正让我的头脑进入这一切,并最终理解这一切 A也称为A 您可以通过添加1

我刚刚开始学习位运算符(尽管我很难找到任何绝对的初学者资源)。我理解二进制文件的工作原理和读取方法,但我不理解以下内容

如果您使用二进制数字37:
00100101
并对其应用~(NOT)运算符,位被翻转到
11010
在我正在阅读的教程中,它说你必须添加一个1作为一种标志,以表示它是负的。因此它变成了
11011011
。我不明白为什么这个新数字不被读为219

在一个相关的注释中,是否有人有任何深度,解释我可以使用的所有资源,以真正让我的头脑进入这一切,并最终理解这一切

A也称为A

您可以通过添加1将1s补码转换为

1s补码和2s补码都是表示负数的不同方式,但现在2s补码几乎被普遍使用

所以,要对2s补码形式的数字求反,只需应用按位NOT并加1,即

-x == ~x + 1
相反,要将2s补码数转换为1s补码,可以将其取反并减去1:

~x == -x - 1
请注意,正数在1s补码和2s补码表示中具有相同的表示形式-只有负数存在差异。例如,对于8位整数:

Decimal    1s complement    2s complement
      0         00000000         00000000
     -0         11111111              n/a
      1         00000001         00000001
     -1         11111110         11111111
      2         00000010         00000010
     -2         11111101         11111110
    127         01111111         01111111
   -127         10000000         10000001
   -128              n/a         10000000
请注意,1s补码有两种十进制0的表示形式:+0和-0,而2s补码有唯一的零表示形式。2s补码还可以表示1s补码中不可用的附加负值(-128,在8位整数的情况下)。

对于“我不明白为什么这个新数字不被理解为219”的答案必须是“因为已知位的解释是有符号的,并且使用2s补码”

位只是位,您必须指定一个解释才能应用规则,例如您正在引用的规则

如果该数字被视为无符号整数,则应将其转换为十进制的219。如果将其视为有符号整数,则应将其转换为-37

您可以通过运行以下命令轻松尝试此操作:

#包括
内部主(空)
{
常数int x=37;
常数y=~x+1;
printf(“%d或%u?\n”,y,y&255);
返回0;
}

它打印“-37或219”,因为在这两种情况下,位的解释不同。
&255
部分只是为了去掉较高值的位,因为它们会使它变得非常混乱(C的
int
整数类型大于8位)。

a-b
相当于
a+~b+1
,因此
0-x
相当于
~x+1
。或者,
a-b
也相当于
~(~a+b)
,因此
0-x
相当于
~(x-1)
。另外,考虑一下:如果你将<代码> ~x添加到<代码> x>代码>,你会得到“所有的”,所以如果你再增加一个,你就会得到零。加上两个数字,得到零意味着它们彼此都是负数。这是否意味着最右边的二进制数字是一个表示负数的标志,而右边的第二个数字代表数字1?谢谢你,保罗。在我所做的几个小时的研究中,我已经看到了很多关于1和2的补充,所以我一定会看一看。
#include <stdio.h>

int main(void)
{
  const int x = 37;
  const int y = ~x + 1;

  printf("%d or %u?\n", y, y & 255);

  return 0;
}