一.操作符的分类
上述的操作符,我们已经讲过算术操作符、赋值操作符、逻辑操作符、条件操作符和部分的单⽬操作符,思考一个问题:上述操作符中有哪些操作符和⼆进制有关系,我们先铺垫⼀下⼆进制的和进制转的知识。
二.二进制和进制转换
其实我们经常听到的2进制、8进制、10进制、16进制,只是数值的不同表⽰形式而已。
如: 二进制由 0 1 组成
八进制由 0 1 2 3 4 5 6 7 组成
十六进制由 0 1 2 3 4 5 6 7 8 9 a b c d e f 组成
如:2进制的01101011,换成8进制:0153; 注:0开头的数字,会被当做8进制计算。
如:2进制的01101011,换成16进制:0x6b; 注:16进制表⽰的时候前⾯加0x
三. 原码、反码、补码
整数的2进制表⽰⽅法有三种: 原码、反码、补码
有符号整数的三种表示⽅法均有符号位和数值位两部分,2进制序列中,最⾼位的1位是被当做符号位,剩余的都是数值位。
符号位都是⽤0表⽰“正”,⽤1表⽰“负”。
正整数的原、反、补码都相同;负整数的三种表⽰⽅法各不相同。
举例:注:对于整形来说:数据存放内存中其实存放的是补码
注:补码得到原码是可以使用:补码符号位不变,数值位取反, + 1的操作!
四.移位操作符 (移动的是二进制位)
移位规则:左边抛弃(最左边向左移动几位)、右边补0
举例:由上述代码可得出:左移一位有乘2的效果(6 * 2 = 12)
移位规则:⾸先右移运算分两种:
注:右移,到底是逻辑右移,还是算术右移取决于编译器的实现,常见的编译器都是算术右移!
举例(算术右移):由上述可得出:右移一位有除2的效果 (-10 / 2 = -5) (注:除了 -1)
警告⚠️:对于移位运算符,不要移动负数位,这个是标准未定义的。如下:
五.位操作符
注:以上他们的操作数必须是整数。
注意:&& : 逻辑与 ; || : 逻辑或 ; ! :逻辑取反 不要搞混淆!
举例:以上代码可得:当操作符为 ^ 时,两变量相同输出结果为0 ; 一变量为0,一变量不为0 其运算结果为不为0的变量。
举例:
⼀道变态的面试题:不能创建临时变量(第三个变量),实现两个数的交换。
问题:如果a和b很大呢?但是没超过整型大小。不能保证a+b不超过整型大小导致栈溢出
以上代码不会栈溢出,因为 ^ : 两补码相同为0,相异为1 是不会产生进位的
练习题1:编写代码实现:求⼀个整数存储在内存中的⼆进制中1的个数。
方法一:
以上代码必须循环32次,循环次数太多,可不可以优化些
方法二:
以上代码达到了优化的效果,但是难以想到。 n & (n - 1)是一个很好计算1的个数的公式
练习题2:⼆进制位置0或者置1。编写代码,将13⼆进制序列的第5位修改为1,然后再改回0
六.单目操作符
单⽬操作符有: ! ++ -- & * + - ~ sizeof (类型) 特点:只有⼀个操作数
在单⽬操作符中只有 & 和 * 没有介绍,这2个操作符,我们放在学习指针的时候学习。