【看书】while(m)m&=m-1,s++;的解释

此讨论是关于【NYOJ】[100]1的个数的补充说明
对于这一题标程给的这一句代码 比较难理解

所以分开来解析

逗号表达式

while(m)m&=m-1,s++;可以写为:

while(m)
    m&=m-1,s++;

首先是”,”所代表的意思
此处是作为 逗号运算符
关于逗号运算符:

逗号运算符可以把两个以上(包含两个)的表达式连接成一个表达式,称为逗号表达式。

逗号运算符的优先级是所有运算符中级别最低的,通常配合 for 循环使用。

所以常用的for(i=0,n=1;i<10;i++)
这种,这个i=0,n=1便是逗号表达式

对于a + b, c = b, c++这个式子

逗号表达式最右边的子表达式的值即为逗号表达式的值。上例中,c++ 的值(c 自增之前的值)即为该表达式的值。

逗号运算符保证左边的子表达式运算结束后才进行右边的子表达式的运算。也就是说,逗号运算符是一个序列点,其左边所有副作用都结束后,才对其右边的子表达式进行运算。因此,上例中,c 得到 b 的值后,才进行自增运算。

验证程序:

#include<stdio.h>
int main() {
    int x,a;
    x=(a=3,6*3);
    printf("a=%d,x=%d\n",a,x);
    x=a=3,6*a;
    printf("a=%d,x=%d\n",a,x);
    return 0;
}

所以while(m)m&=m-1,s++;可看作是两条循环语句

m&=m-1;
s++;

位运算

s++ 很好理解
那么m&=m-1;的解释又应该怎么说呢

&在这里应是按位与
也就是二进制的数每个位,两个数都是 1这个位才是1

常用的
if(a&1) 就相当于如果a是奇数
因为如果a是奇数 那么最后一位就是1
a&1 结果也应该是1
如果是偶数 那么a&1==0

在这里 m&=m-1 =>m=m&m-1
为什么这样写能计算出1的个数呢

举例
5的二进制 101
则运算过程为
100&101==100 =>s==1
100&011==0 =>s==2

分析
m&m-1 使得如果最后一位是1
那么结果便相当于去除了最后以为的1并把结果+1
如果最后一位是0
那么其前一个1位在运算后会变成0 并结果+1
而且使得其自身还是为0

所以通过这种方式一次一次把1位拨成0位
然后记录次数
从而可以得出数字二进制有几个1

也是二进制运算很奇妙的一种体现

参考文章:
《C语言程序设计——贾宗璞 许合利》
c语言中逗号运算符的功能和使用方法_百度知道
位运算_百度百科

posted @ 2016-01-30 00:42  BoilTask  阅读(44)  评论(0编辑  收藏  举报