为什么“ -10&5”的结果等于4?当按位AND应用于负数时会发生什么?

-11 c bit-manipulation operators bitwise-operators negative-number

我已经编写并编译了以下代码:

void main()
{ 
    printf("%d", -10 & 5);
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,它输出值4。为什么该程序的输出为4?

Eri*_*hil 6

在C中,根据二进制的结果&,每个位取决于操作数中的两个相应位。如果两个操作数中相同位置的位都设置为(1),则结果中将其设置为1。如果在任一操作数中清除为(0),则结果为清除。例如,给定位0011和0101,&运算符将产生0001,因为只有在最后一个位置才在两个操作数中都设置了该位。

您可能已经知道,正整数用二进制表示。位的位置从“右侧”的0开始编号,然后是下一个位置的1、2、3,依此类推。位置i中的位代表2 i的值,因此位0代表1,位1代表2,位2代表4,位3代表8,位4代表16,依此类推。所有位表示的值是设置为1的位的值的总和。所以101表示5,因为设置了2 2 = 4和2 0 = 1的位,并且4 + 1 = 5。

C标准指定了C实现可以用来表示负数的三个规则(在C 2018 6.2.6.2 2中):

  • 这些位之一代表一个符号。如果符号位为0,则该值与上述相同。如果符号位为1,则取反。因此,如果第一位是符号位,则5是0101是5,而?5是1101。这称为符号和大小
  • 这些位之一代表一个符号,如果数字为负,则所有位都将反转。所以5是0101,?5是1010。这被称为一个补数
  • 这些位之一代表一个符号,如果数字为负(我们称其为x),则将这些位设置为将用于2 N?的模式。x,其中N是位数。例如,对于四个位,2 N = 16,而5为0101,而?5用16?5 = 11的位表示,即1011。这称为二进制补码

在早期的计算机硬件和软件中,尝试了所有上述方法。最后的二进制补码在现代整数计算中占绝对优势。(大多数浮点使用符号和大小。)尽管如此,C标准仍然允许实现使用任何方法。

因此,的结果-10 & 5取决于实现。我将说明如何使用八位,并留出一个空格将它们分成两组,每组四位,以提高可视性:

补码:

  • 10用1111 0110表示(256 10 = 246 = 128 + 64 + 32 + 16 + 4 + 2),5使用0000 0101,并且?10 & 5是0000 0100,表示4。

补充:

  • Δ10用1111 0101表示,5使用0000 0101,并且?10 & 5是0000 0101,表示5。

有符号和大小:

  • 1010用1000 1010表示,5使用0000 0101,并且-10 & 5是0000 0000,表示0。

因此,符合C标准的C实现可能会针对产生0、4或5 -10 & 5,但是4是迄今为止最常见的结果。