一.运算符分类
1.算术运算符(用于各类数值运算)
常见的有:
+ (加) - (减) * (乘) /(除)
% (求余,又称模运算) 注意负数的求余(如(-5)%6==-5,(-12)%5==-2)
++ (自加)
注意:a++与++a的区别 a++和++a都是将a的值+1再赋给a,但是a++和++a所代表的值不一样,(a++)的值为a的原值,而(++a)的值为a+1;如a变量原值为0,则(a++)==0;而(++a)==1
-- ( 自减) 其与自加相同
2.关系运算符 (用于比较运算)
常见的有:
> < ==(注意是两个=) >= <= !=(不等于)
3.逻辑运算符 (用于逻辑运算)
&&(与) ||(或) !(非)
说明:若事件A和B,则(A&&B)的值在A和B都成立的时候为1,否则为0;(A||B)的值在A和B都为假时为0,其余都为1。
4.位操作运算符 (参与运算的量,按二进制进行运算)
位与(&)
对二进制的数进行位运算 只有两个同时为1时位与(&)的值才为1,否则位0,而且是一位一位的额进行比较的 如十进制4和3
4的二进制 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
3的二进制 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
4&3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
所以最后的结果为0
与运算的特殊作用
(1)清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
(2)取一个数中指定位
方法:找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。
例:设X=10101110,
取X的低4位,用 X & 0000 1111 = 0000 1110 即可得到;
还可用来取X的2、4、6位。
(3)判断一个数的指定为是否为1
方法:若想要判断X的第四位是否为1,这将X与一个第四位为1,其他为0的数进行位与(&)运算,若值为0,则的四位值不为1。
位或(|)
位或(|)运算规则大致与位与(&)相同,但 位或(|)只有当两个都为0时其值才为0,其它都为1。
或运算”特殊作用:
常用来对一个数据的某些位置1。
方法:找到一个数,对应X要置1的位,该数的对应位为1,其余位为零。此数与X相或可使X中的某些位置1。
例:将X=10100000的低4位置1 ,用 X | 0000 1111 = 1010 1111即可得到。
位非(~)(取反运算符)(参加运算的一个数据,按二进制位进行“取反”运算。)
运算规则
对一个数的二进制取反,1变为0,0变为1。
如:~1=0; ~0=1;
位异或(^)
运算规则
运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;
例如:10^-9 即 0000 1010 ^ 1111 0111 = 1111 1101(补码) 原码即为1000 0011 即10^-9 = -3
*(注意)补充:原码 反码 补码
原码 机器只能读存二进制的数,原码就是这个数的二进制数,其最高位表示符号,其中1 表示负数,0表示正数。
反码 正数的反码和原码相等,而负数的反码除最高位表示正负符号的1不变,其他的每一 位上1变为0,0变为1。
补码 正数的补码的原码相等,而负数的补码则是在反码的基础上+1,如:-3
原码 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
反码 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
补码 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
(至于详细的内容就不在这里提了,想要了解其中的原理的,如为什么补码要加一,自己去找那些大神的详细解说)
“异或运算”的特殊作用:
(1)使特定位翻转 找一个数,对应X要翻转的各位,该数的对应位为1,其余位为零,此数与X对应位异或即可。
(2)与0相异或,保留原值 ,X ^ 0000 0000 = 1010 1110。
(3)交换a和b
方法一 | 方法二 |
---|---|
1.a=a^b | 1.a= a-b |
2.b=b^a | 2.b= a+b |
3.a=a^b | 3.a= b-a |
左移(<<)
将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
例:a = a << 2 将a的二进制位左移2位,右补0,
左移1位后a = a * 2;
若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
右移(>>)
将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
>> 运算符把 expression1 的所有位向右移 expression2 指定的位数。expression1 的符号位被用来填充右移后左边空出来的位。向右移出的位被丢弃。
5.赋值运算符 (用于赋值运算)
简单赋值(=)
复合算术赋值(+=,-=,=,/=,%=)
复合位运算赋值(&=,|=,^=,>>=,<<=)
这里就不再展开了,这里因该没什么难理解的地方
6.条件运算符
?:(三目运算符)
常见型式
表达式1 ? 表达式2 :表达式3
理解:如果表达式1为true,则整个表达式的值为 表达式2的值(即,冒号左边的值);
如果表达式1为false,则整个表达式的值为 表达式3的值(即,冒号右边的值);
注意:表达式2,3只会运行一个,至于运行的是哪一个要看表达式1是否成立
7.逗号运算符 用于把若干表达式组合成一个表达式(,)
一般形式:
表达式1,表达式2
注意事项:
逗号表达式的求解过程是:先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值
8.指针运算符 用于取内容(*)和取地址(&)二种运算。
9.求字节数运算符 sizeof
注意:sizeof(数组名),其中的数组名代表整个数组。
补充:
数组名代表整个数组的两个中情况
1. sizeof(数组名)
2. &数组名
10.特殊运算符 有
括号()
下标[]
arr[3]=*(arr+3)
成员(→,.)
很多时候容易把->和.搞混淆了,下边为他们的区别:
一般情况下用“.”,只需要声明一个结构体。格式是,结构体类型名+结构体名。然后用结构体名加“.”加域名就可以引用域 了。因为自动分配了结构体的内存。
而用“->”,则要声明一个结构体的指针,还要手动开辟一个该结构体的内存,然后把返回的指针给声明的结构体指针,才能用“->”正确引用。否则内存中只分配了指针的内存,没有分配结构体的内存,导致想要的结构体实际上是不存在。这时候用“->”引用自然出错了,因为没有结构体,自然没有结构体的域了。
此外,(*a).b 等价于 a->b
补充:
1、单目运算符:
只对一个变量进行操作。
a++;
2、双目运算符:
对两个变量进行操作;
a=1; b=3; c=a+b;就是双目运算符;
3、三目运算符:
对三个变量进行操作;
二.运算符的优先级。
上图出自《c陷阱与缺陷》中的一图
运算优先级最高的是前述运算符(如函数的调用)。仅次于前述运算符的是单目运算符,在真正意义上的运算符中,它们的优先级最高(注意:类型转换也是单目运算符,它的优先级和其他单目运算符优先级一样)并且单目运算符是自右至左结合的
优先级比单目运算符要低的,接下来就是双目运算符。在双目运算符中,算数运算符(+ - * / %)的优先级最高,移位运算(<< >>)符次之,关系运算符(> < <= >=)再次之,接着是逻辑运算符,赋值运算符,最后是条件运算符(三目运算符)。
1.任何一个逻辑运算符的优先级低于任何一个关系运算符。
2.移位运算符的优先级比算数运算符要低,但是比关系运算符要高
同一类型运算符的相对优先级
乘法除法求余优先级相同,加法减法优先级相同,两个移位运算符优先级相同。
但是六个关系运算符优先级并不相同,运算符==和!=的优先级要低于其他四种运算符的优先级
任何两个逻辑运算符的优先级不同,所有按位运算符要比顺序运算符的优先级高,每个“与”运算符要比“或”运算符的优先级要高,而按位异或的优先级则是位与按位与和按位或之间。
通过以上的规律和图表来记运算符的优先级就会显得非常轻松了!