首页 > 解决方案 > 当按位与应用于负数时会发生什么?

问题描述

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

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

标签: cbit-manipulationoperatorsbitwise-operatorsnegative-number

解决方案


在 C 中,在 binary 的结果中&,每个位都取决于操作数中对应的两个位。如果相同位置的位在两个操作数中都设置为 (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 -<em>x 的模式,其中N是位数。例如,对于四位,2 N = 16,5 是 0101,而 −5 用 16−5 = 11 的位表示,即 1011。这称为二进制补码

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

Because of this, the result of -10 & 5 is implementation-dependent. I will illustrate using eight bits, with a space to group them into two sets of four bits for visibility:

With two’s complement:

  • −10 is represented with 1111 0110 (256 − 10 = 246 = 128+64+32+16+4+2), 5 uses 0000 0101, and −10 & 5 is 0000 0100, which represents 4.

With one’s complement:

  • −10 is represented with 1111 0101, 5 uses 0000 0101, and −10 & 5 is 0000 0101, which represents 5.

With sign and magnitude:

  • −10 is represented with 1000 1010, 5 uses 0000 0101, and -10 & 5 is 0000 0000, which represents 0.

Thus, a C implementation that conforms to the C standard could produce 0, 4, or 5 for -10 & 5, but 4 is by far the most common result.


推荐阅读