按位运算符和if条件语句

3

我正在阅读《C语言程序设计》这本书,在第2.10节中,他们给出了以下示例:

/*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;

}

这个函数的作用是计算x中为1的位数。

我理解if语句的作用是“屏蔽”掉某些位,但是我不明白如何实现?

这个条件基本上是:

if(x&01==1)?

我不理解这个条件。

(x&01) 意味着什么?

此外,我不明白循环何时停止?当所有位都向右移动并且所有腾空的单元格现在都是0时,循环就会停止吗?

我只是无法理解这种方法的工作原理,而且我已经寻找了相当长时间的解决方案。

谢谢。


你尝试过逐步调试吗?通过检查每一步之后变量的值,你可以理解程序。 - buc
1
更准确地说,条件 if (x & 01) 等同于 if ((x & 01) != 0),尽管在实践中,(x & 01) 只能获得非零值 1。一般来说,if (expr) 等同于 if ((expr) != 0),这就是我最初的改写。 - Jonathan Leffler
@JonathanLeffler,您能否解释一下 if (x&01) 这个条件是什么意思?我很难理解。它是将 x 与 0 进行 & 操作,然后将结果与 1 进行比较吗? - Assaf
2
如果你需要解释位运算符,而不是在if语句的上下文中使用位运算符,那么你正在提出一个有些不同、明显更大的问题。01是一个八进制常量,等于001'\001'10x10x00000001等,也就是“一”。两个值的按位“与”比较每个参数(在x1中)中的每个位位置,并在相应的结果中产生一个位,如果两个输入位都是1,则为1,否则为0。在这种情况下,唯一可能产生非零值的位是LSB,即最低有效位。 - Jonathan Leffler
4个回答

5

让我们使用while循环重写这个函数。

int bitcount(unsigned x)
{
    int b = 0;
    while (x != 0) {
        if (x & 0x1)
            b++;
        x = x >> 1;
    }

    return b;
}

注意,每次循环我们都会做两件事情:
  1. 如果数字的最低位是高位(即数字为奇数),则将计数器加一。
  2. 每次迭代,我们将数字除以2 (x = x >> 1)

这个数字是十六进制的吗?所以你写0x1就是因为这个原因? - Assaf
1
@Alan:从技术上讲,01是八进制,1是十进制,0x01是十六进制,但它们都具有相同的值1。我只是使用十六进制,因为这是我在处理移位时的思考方式。不过这并没有任何区别。 - Bill Lynch
谢谢,但我问这个问题是因为你写的是x&0x1而不是x&01。你能解释一下这个条件的含义吗?这是最令人困惑的地方... - Assaf
2
不同的数字表示法只对人类读者有意义。对计算机来说,一切都是二进制的。 - Fiddling Bits

3

这个条件基本上是:if(x&01==1)吗?

可以这样理解,换句话说,如果“x & 01”不为零,则满足该条件。

此外,我不明白循环何时停止?只有当所有位都向右移动并且所有空出的单元现在都为0时,循环才会停止吗?

当你执行 x>>=1 时,你将 x 的所有位向右移动一步。如果你拿起笔和纸,你也会意识到这与除以2相同。什么时候会停止呢?当 x 变成零时:x!=0


3

你对循环终止的理解是正确的。

但是有一个重要提示:此代码仅在xunsigned时有效。因为对于有符号整数,在右移时会将1位附加为MSB。

现在是(x & 01 == 1)

它基本上将x的值与十进制数字1进行AND运算,如下所示:

x:           0001000100001110(一些随机的32位值)
1:           0000000000000001
&
结果:  0000000000000000

这个结果的原因:
AND操作按位进行逻辑AND。您可以在互联网上查看AND操作的真值表。

给你一个提示/建议:这不是计算有符号/无符号数字中所有1位的最佳方法。存在一种方法,它可以在与数字中的1位数相同的循环迭代次数内计算1位。尝试自己实现或搜索更好的方法。


0

if(x&01) 的意思是:

例如1:x的二进制值为:1011101
                      01的二进制值为:0000001
                      & 是二进制AND运算符:---------
                                       结果为:0000001

例如2:x的二进制值为:1011100(最后一位为0)
                      01的二进制值为:0000001
                      & 是二进制AND运算符:---------
                                       结果为:0000000

因此,这意味着if(x&01)
根据x的最后一位值“1”或“0”,此条件仅返回两个值“0000001”或“0000000”。

int bitcount(unsigned x)
x被定义为无符号数
这意味着x只能是正数。
因为无符号表示仅为正数。
0000000不是正数=不是无符号数。

所以 b++; :
由于"x"仅定义为正数,因此"x"不会接受0000000值,因为0000000不是正数。这将只计算值为0000001的值。

最后 x >>= 1 :
这将把x的位向右移动1个位置,并在最左侧创建新的位插槽并填充“0”值。

x != 0:
“for”循环将在右侧移位过程的最后当x变成0000000时结束。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接