c语言操作符练习总结
sizeof()的坑🕳
1 |
|
观察上端代码,思考一下输出结果是什么?
首先定义了一个全局变量,全局变量没有赋值,默认值为0;然后i–;i变成了-1.你也许会说sizeof(-1),-1是int类型的,占4个字节,-1<4,结果不就是<
吗!其实不然,结果是>
,-1大于4?数学是体育老师教的!
原因在于sizeof()的返回值是无符号整型,也就是unsigned int,两数比较时,编译器会将左侧的值也转换成无符号整数,-1在内存中存储的是全1,即11111111111111111111111111111111,无符号嘛,会认为这是一个很大的数,所以最后输出了>
.
所以当一个数与sizeof()直接比较时,就要小心咯,可能会有意想不到的结果。
运算符优先级
1 |
|
观察上段代码,输出结果是什么?很烦这种代码,虽然没什么意义,但既然错了,还是记录下吧。主要考察操作符的优先级和结合性。主要说两点,一是逗号表达式的优先级最低,所以b= ++c , c++ , ++a , a++;
先算b=++a,然后再算逗号后面的操作。二是+=
操作符的优先级也很低,所以在b += a++ + c
中先计算a++ +c
,再将结果加上b后赋值给b。
二进制中1的个数
求二进制中1的个数,有很多方法。
方法一:利用按位与&
和移位>>
运算符。一个数按位与&1,可以求得这个数二进制的最低位。只求最低位哪行啊,我要的是所有位上1的个数,结合移位运算符,(n>>1)&1,得到的就是第二位,(n>>2)&1,得到的就是第三位,一直到31,得到一次加一次,就得到了二进制中所有的1.
1 | int main() |
方法二:利用%和/运算符,比如1987,1987%10,得到了后一位7,1987/10%10,得到了8,1987/100%10,得到了9,1987%1000/10,得到了1。十进制/10%10,二进制自然就/2%2。值得注意的是数的类型要定义为unsigned int
,否则该方法只适用于正整数。
1 | int main() |
方法三:利用表达式n=n&(n-1)
,计算表达式执行的次数,n为0时结束循环。如下图所示:
1 | int main() |
两个数二进制不同位的个数
有了上道题的基础,这道题就迎刃而解了。
思路一:默认最低位是第0位,n>>i&1可以求得第i位的二进制数,如果两数不等,计数器加一即可。
1 | int main() |
思路二:利用异或^
运算符,两数异或,相同位为0,不同位为1。对异或后的数求二进制中1的个数,便得到了二进制中不同位的个数。
1 | int main() |