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

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


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

最佳答案

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

您可能已经知道,正整数用二进制表示。这些位的位置从“右侧”的0开始编号,然后是下一个位置的1、2、3等。位置i中的位代表2i的值,因此位0代表1,位1代表2,位2代表4,位3代表8,位4代表16,依此类推。所有位表示的值是设置为1的位的值的总和。所以101表示5,因为设置了22 = 4和20 = 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),则以将用于2N-x的模式设置这些位,其中N是位数。例如,对于4位,2N = 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。


有符号和大小:


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


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

08-16 13:15