K&R C 第 2 章赋值运算符和表达式

K&R C chapter 2 assignment operators and expressions

赋值运算符不是我期望的困难。到目前为止,本节中的所有内容都很熟悉,但他们解释它的方式让它看起来很陌生。我认为这是我感到困惑的位运算符。

无论如何这是我没有得到的部分。

The function bitcount counts the number of 1-bits in its integer argument.

/*bitcount: count 1 bits in x */
int bitcount (unsigned x)

{
  int b;

  for(b=0; x != 0; x >>= 1) {
    if(x & 01) 
      b++;
  return b;
}

Declaring the argument x to be unsigned ensures that when it is right-shifted, vacated bits will be filled with zeros, not sign bits, regardless of the machine the program is run on.

并不是说我真的理解代码,但最后一句话让我最困惑。这是什么意思? “符号位”表示“一”吗?这与二进制补码有关吗?

我真的很难完成按位运算。谁能推荐一些全面的 material 来补充本书中的按位内容?

假设x是二进制补码。为了便于说明,让我们使用八位宽度。 (C 总是以更宽的宽度移动,至少 int。)

如果x是64(010000002),我们将它右移一位,我们得到32(001000002).当我们重复它时,我们得到 16 (000100002), 8 (000010002), 4 (000001002)、2 (000000102) 和 1 (000000012).

x为-64时,补码表示为110000002。如果我们将其右移并引入 0 位,则这些位为 011000002,表示 64+32 = 96。因此 −64 变为 96。现在,如果一个只是在使用位。但是,如果我们想使用移位来除数,我们需要 −32,而不是 96。−32 的位是 111000002。所以我们可以通过引入 1 位而不是 0 位来获得它。 −16 的位是 111100002。则-8、-4、-2、-1分别为111110002、111111002、111111102, 111111112。在每种情况下,我们在移位时都带入一个 1 位。

因此,如果我们想使用位移位进行除法,那么一位位移有一个简单的规则:将所有位右移一个位置并保持符号位不变(0 或 1)。如果我们要移动多于一位,请继续复制符号位。

这叫做算术右移。因此,我们有两种右移:一种是复制符号位的算术右移,另一种是带入 0 位的逻辑右移。

对于无符号类型,C 标准规定右移是合乎逻辑的。

对于有符号类型,C 标准并没有说明它是算术类型还是逻辑类型。它将它留给实现来定义该实现使用的(或可能定义其他东西)。这可能是由于历史原因;早期的机器可能没有提供算术右移指令(甚至可能没有使用二进制补码),尽管现在似乎很难想象。

因此,当您编写向右移位的代码并且希望确定将得到的结果时,您可以使用无符号类型来确保得到逻辑移位。

在二进制补码表示中,最高位保留给符号。正数最高位为 0,负数最高位为 1。 如果将负数的位右移,则最初位于最高位的 1 将移至下一个较低位,如果继续移位,最终将以最低位结束。 在代码中,for 循环将 x 的位移动一位并将移位后的值分配给 x。

for (b = 0; x != 0; x >>=1 )

首先b,用于统计数字中1位的个数设置为0。

继续循环的条件是 x != 0。当所有的 1 位从 x 移出时,唯一剩下的将是 0 位。 x 将等于 0.

每次迭代后执行的操作是将x中的值右移1。

循环体中的 if 条件对 x 执行按位与操作。位掩码的值为 1,这是 int 值的一个实例,除最低位外所有位均为 0。如果最低位为 1,则该 AND 运算将评估为 1(或在 C 中为真),如果最低位为 0,则为 0(或在 C 中为假)。如果 if 条件为是的。