当按位与应用于负数时会发生什么?

What happens when bitwise AND is applied to negative numbers?

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

void main()
{ 
    printf("%d", -10 & 5);
}

在C语言中,二进制&的结果中,每一位都依赖于操作数中对应的两个位。如果在两个操作数中相同位置的位都设置为 (1),则在结果中设置它。如果任一操作数中的值都为零,则结果中的值也为零。例如,给定位 0011 和 0101,& 运算符将产生 0001,因为只有最后一个位置才是两个操作数中设置的位。

您可能已经知道正整数是用二进制表示的。位位置从“右侧”的 0 开始编号,然后是下一个位置的 1、2、3,依此类推。 i位置的bit表示的值为2i,所以bit 0表示1,bit 1代表2,第2位代表4,第3位代表8,第4位代表16,依此类推。所有位表示的值是设置为1的位的值之和。所以101表示5,因为22 = 4和2[=45的位=]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 的模式Nx,其中N为位。比如4位,2N = 16,5就是0101,-5用16−5 =的位表示11,即1011。这叫做二的补

在早期的计算机硬件和软件中,以上都是尝试过的。最后一个,二进制补码,在现代整数计算中占据压倒性优势。 (大多数 floating-point 使用符号和大小。)尽管如此,C 标准仍然允许实现使用任何方法。

因此,-10 & 5的结果是implementation-dependent。我将使用八位进行说明,并使用 space 将它们分为两组,每组四位以提高可见性:

补码:

  • −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.

有符号和大小:

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

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