大部分操作符都是以二进制为基础使用的,所以想要学习操作符就必须先学习二进制想关的知识。
1、二进制
二进制、八进制、十进制、十六进制,这些进制是什么意思———其实就是数值的不同表达形式。
例:数值15各进制表达形式:
1.15的二进制:1111
2.15的八进制:17
3.15的十进制:15
4.15的十六进制:f
1.1详解各进制(以二进制为主)
首先从十进制开始,十进制就是我们日常生活中所用的进制:
*满10进1
*每一位都是由0~9的数字组成的
二进制也相同:
*满2进1
*每一位都是由0~1的数字组成的
十六进制:
1.2各进制的转换
1.2.1权重
权重:可以理解为进制中每位所代表的数值大小。
以二进制为例:
从右向左是: 2^0、2^1、2^2……
其他进制和2进制是类似的 ,都是从右向左次方依次增加。
例如:十进制从右向左权重依次为:10^0、10^1、10^2……
1.2.2十进制转二进制
1.2.3 二进制转八进制和八进制
1.二进制转八进制
八进制的每一位由0~7 的数字组成,如果每位都写成二进制,最多3个而二进制位就足够了。所以在二进制转八进制的时候,从二进制序列中右边低位每3个二进制位换算成一个8进制位即可,剩余不够3个的二进制位直接换算即可。
2.二进制转十六进制
十六进制的每一位由0~9,a~f 的数字组成,如果每位都写成二进制,最多4个二进制位就足够了。所以在二进制转十六进制的时候,从二进制序列中右边低位每4个二进制位换算成一个十六进制位即可,剩余不够4个的二进制位直接换算即可。
2.原码、反码、补码
整数的二进制位有三种表达形式:原码,反码,补码(在计算机中存储的形式)。三种表达形式都由符号位和数值位组成,最高的一位被当作符号位,剩下的都是数值位。符号位如果是“1”,则表示为负数;如果是“0”,则为正。
原码:最高位是符号位,其余位是数值的绝对值。
反码:原码的符号位不变,其余位取反(1取反为0,0取反为1)。
补码:反码加1。
原码->补码:取反 加1. 补码->原码:取反 加1
正数的原码,反码,补码相同。
整形在计算机中存放的是补码——使用补码可以将符号位和数值位统一处理,同时加减法也可以统一处理(cpu中只有加法器)。此外,原码补码相互转换的过程是相同的不需要额外的硬件电路。
3.移位操作符
移位操作符包含左移操作符和右移操作符。
*移位操作符只能是整数,且是正整数(负整数未定义)。移位操作符作用于二进制。
3.1左移操作符—— “<<”
移动规则:左边抛弃,右边补0。
num<<1是不会改变num原来的值的。
3.2右移操作符——“>>”
右移操作符分两种:
1.算术右移:左边用该值的符号位填充,右边抛弃。
2.逻辑右移:右边抛弃,左边补0。
选择哪种取决于编译器,常见的编译器都是算术右移动。
移位与按位操作符的使用:http://t.csdn.cn/1Qm7B
4.位操作符
位操作符须作用于二进制中,且操作数必须为整数。又因为整形在计算机中是以补码存储的,所以其实操作的是补码。
4.1按位与——“&”
运算方法——有0则0,两个都为1才为1。
4.2按位或——“|”
运算方法——有1则1,两个都为0才为0。
按位或与移位操作符的使用:
4.3按位异或——“^”
运算方法——相同为0,相异为1。
a^a=0 , 0^a=a
a^a^b=b , a^b^a=b(按位异或支持交换律)
按位异或的使用:http://t.csdn.cn/CKcht
4.4按位取反——“~”
运算方法:是0的变成1,是1的变成0
将a的二进制位的第五位改成0:
如果直接通过二进制位第五位为0的数来按位与,那么计算这个数也成为了一个难点。
那么这时候就用到了按位取反操作符:首先明确我们需要的数为二进制位第五位为0,其余位位1的数。接着我们思考如何得到这个数,全是1比较大,那么我们就取反得到以0为主的数,现在问题就变成了如何得到二进制位第五位为1其余位为0的数。通过1<<4得到该数,最后我们再次取反就得到了我们需要的数。
5.逗号表达式 、下标引用操作符
5.1逗号表达式
exp1,exp2,exp3, ……expn
逗号表达式就是用逗号隔开的多个表达式。
逗号表达式是从左向右依次计算,整个表达式的结果是最后一个表达式的结果。
while语句中逗号表达式的应用(实际操作不会这么写了解即可):将第二个while语句使用逗号表达式改写即成为了第一个while语句,但第一个while语句不管条件(a<5)是否成立都会执行一次,而第二个while语句会先判断条件是否成立 .
5.2下标引用操作符 ——“[ ]”
操作数:一个数组名+一个索引值
int arr[10]=0; //创建数组
arr[7]=7; //实用下标引用操作符
//[]的两个操作数是 arr和7
6.操作符的两大属性
操作符有两大重要属性:优先级、结合性。该两大属性基本上决定了表达式求值的计算顺序。
6.1优先级
当一个表达式里出现多个运算符,那哪个运算符该优先执行呢。每个运算符的优先级是不一样的。
1+2*3
上述表达式中既有加号运算符(+),又有乘法运算符(*),那该先算哪个呢。
由于“ * ” 的优先级高于“ + ”的优先级,所以先算2*3.
6.2结合性
当两个运算符优先级相同时,优先级就失去了作用,这时候就该看运算符的结合性。根据运算符是左结合(从左到右)还是右结合,决定执行顺序。大部分运算符是左结合,还有少部分是右结合,如经典的赋值操作符(=)。
关于操作符的优先级和结合性可以参考该网站:C 运算符优先级 - cppreference.com
7.错误案例
你知道这串代码是如何运行的吗?
不同的编译器可能出现不同的不同的结果,下面两种情况看着没问题,实际上也没问题。
为什么会出现这种情况呢?因为在第一个+执行的时候,第三个前置++是否执行时不确定的。因为通过操作符的优先级和结合性时无法决定第一个+和第三个前置++的执行顺序的。
总结 :即使有了操作符的优先级和结合性,我们写的表达式任然有可能不能通过操作符的属性来确定唯一的计算路径。所以我们写得表达式不能够太复杂化,尽量简单化。