文章目录
- 算术操作符
- 移位操作符
- 位操作符
- &:按位与(与门)
-
& 的应用
- | :按位或(或门)
- ^ :异或(非门)
- 赋值操作符
- 单目操作符
- 关系操作符
- 逻辑操作符
- 逻辑与:&& ——— 并且
- 逻辑或: | | ——— 或者
- 逗号操作符
前言
这里 + - 等一些简单的操作符没有做出解释(考虑到大家都会用 -_- )
再推荐一个新手也能上手的刷题网站:
LeetCode: https://leetcode-cn.com/problemset/all/
算术操作符
% :取模操作符两端的操作数只能是整型
移位操作符(移的是二进制的位)
注:移位操作符的操作数只能是整数
<< :
左移是逻辑左移,把整个二进制数向左,符号位也会跟着,如果符号位改变了,就是改变了符号,不要不可思议哦(只是少见)
而且左移相当于乘了2(这个可用于:不使用pow函数来表示 2的n次方<其中一种> )
(相反,右移一位相当于除2)
>> :
右移是:算术右移,移动后左边补的数按原来的符号来补,原来是1(负数),左边补上1,是 0 就补0(简单来说就是左移会保留正负号<保号性>)
注:不管 >> 还是 << , 不会改变原来变量的值(无副作用)
etc. int a = 10;
b = a >> 1; 意思是使用 >> 后不会改变a的值(当然)
简单来说:
>> : 逻辑左移(可能变号):整个二进制左移(符号也跟着左移),当然不用说右边是补0
>> : 算术右移(不会变号):整个二进制右移(左边就空了,按符号位来补),右边多出来就裁掉
位操作符:按位与、或、异或(非)(& 、| 、^)
& 、 | 、^ 中是将内存中的值进行操作,而数值在内存中是其补码形式,所以 与或非 是进行补码之间的操作
& 、 | 、^ 操作时处理的是二进制 0 / 1 ,在它们进行操作时 我们可以把 1 或 0 看做 真 或 假 的性质,这样便于我们理解和自己推算
1、&:按位与(与门)
补码之间的操作:针对的是操作数对应的 0 或 1
如果操作数对应的二进制数都为 1 (理解为都为真),输出 1 (输出真)
如果操作数对应的二进制数一个为 1 (真),一个为 0(假),输出 0 (输出假)
两个为 0 (都为假),那输出 0 (假)
(和高中数学一样,只要一个为假,那就是假,两真才为真)
etc.
// int a = 2
// int b = -3
int c = a & b;
// a 的补码:0000 0000 0000 0000 0000 0000 0000 0010
// b 的补码:1000 0000 0000 0000 0000 0000 0000 0011
// a & b :0000 0000 0000 0000 0000 0000 0000 0010
所以 a & b 的值为 2
a、& 的应用
以n举例:
使用 n & (n - 1) 每次可以去掉二进制最右边的一个1
这样可以用来统计一个数二进制中 1 的个数
具体见:n按位与(n-1)来判断二进制中1的个数
2、 | :按位或(或门)
同样是针对补码间:
若操作数对应的二进制数都为 1 (都为真),输出 1 (真)
若操作数对应的二进制数有一个为 1 (真),输出 1 (真)
若操作数对应的二进制数都为 0 (都为假),才输出 0 (假)
3、 ^ :异或(非门)
同样是针对补码间:但是这里不用认为 1 / 0 为 真假概念,也不是很好理解
如果两个对应二进制数相同,输出 0 (不管对应的都为 1 还是 0 ,输出为 0 )
如果两个对应二进制数不相同,输出 1
(非门嘛,倒着的)
异或支持交换律:a ^ b ^ c = a ^ (b ^ c)
所以可开始运用:(若 a = 3, b = -1 )
a ^ a
// a 的补码 :0000 0000 0000 0000 0000 0000 0000 0011
// a 的补码 :0000 0000 0000 0000 0000 0000 0000 0011
// a ^ a :0000 0000 0000 0000 0000 0000 0000 0000
仔细思考:因为 异或 对应二进制数相同,输出 0 ,那么上面的 a 不管取何值,结果都全是 0
所以知道:当两个相等的变量使用异或 ^ 时(或常数,表达式等),结果都为 0
而 0 ^ a 发现有 1 的位置还是 1, 本来是 0 的还是 0 ,所以 0 ^ a 结果依然是 a
这样通过一些方法可以交换两个变量的值:
a = a ^ b; //先定义一下
b = a ^ b; //因为a被赋成a^b,代换一下就是 a ^ b ^ b ,即是 a 的值
a = a ^ b; //再代换一下,a = a ^ b ^ a ,实现交换操作
具体见:交换两个变量的值多种方法
赋值操作符:
+=
-=
*=
/=
%=
>>=
&=
| =
^=
可完成复合效果:
int x += 1; 等价于下面的代码:
// int x = 0;
// x = x + 1;
单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(字节为单位)
~ 对一个数按位取反
-- 前置或后置 --
++ 前置或后置 ++
* 解引用操作符(间接引用操作符)
() 强制类型装换
etc.
b = a++;
相当于先把 a 赋给 b ,a 再自增 1,而且不管是在赋值时是这样,在函数传参时( 如: founction (a++) )等也是
所以把 a++ 可以理解为 两行代码,先把 a 进行赋值或传参等操作这一行代码(或函数调用完后), 再进行 a + 1 这一步(这一行代码)
并且一定要注意,使用 ++ 或 -- 时,会把变量的值改变(相当于有副作用)
etc.
a++;
b = a + 1; //上一行 ++ 会改变a的值,而这里的 b = a + 1 不会
关系操作符
>
=
>=
!= 测试 是否不相等
== 测试 是否相等
逻辑操作符
逻辑与:&& ——— 并且
一定要注意其短路性:&& 左边一旦出现假,&& 右边就不进行计算
etc.
//可看成 ( a++ && ++b ) && c++ ···
//把()括号里的看做一个整体,a 为假,( ) 整体为假, ( ) && c++ 为假
//后面也同样可以这样可理解
逻辑或: | | ——— 或者
注意分清 || 的短路性:和 && 的短路性不同,如果没遇到真,就一直进行计算使用了 | | 的表达式, 直到遇到真为止(它就要计算完一个逻辑为真的表达式,它只要一个,一个就好......)
因为一旦有真整个有关 | | 的表达式就有结果了:一个为真,整个表达式为真,停止计算,该判断部分输出 1
注:不管 && 还是 || ,逻辑操作符只关注真和假,而且逻辑表达式的结果为 1 或 0 (只有真假)
etc.
逻辑非:!
逗号操作符(优先级最低)
逗号操作符的结果为最后一个表达式的结果
并且操作符中的每个表达式会生效,而且是从左至右算过去(左结合性)
虽然只会输出最后一个表达式,但是其他表达式也生效了
如果没括号:b = a*2, --b, c++, c - a;
没括号导致 =操作符 与 逗号操作符 相遇,得考虑优先级问题
逗号表达式与赋值之间的