今天我们来详详细细的介绍一下异或操作符(^)
异或(^)操作符同与(&)操作符、或(|)操作符一样,都是来操作二进制底层的,是通过二进制每一数位来进行操作,所以他们也统称为–位操作符。
异或(^)操作符:相同为1,不同为0.
简单跟大家举个例子
int main()
{
int a = 15;
//15二进制:0000 0000 0000 0000 0000 0000 0000 1111
int b = 10;
//10二进制:0000 0000 0000 0000 0000 0000 0000 1010
int c = a ^ b;
//a ^ b : 0000 0000 0000 0000 0000 0000 0000 1111
// 0000 0000 0000 0000 0000 0000 0000 1010
//结果 : 0000 0000 0000 0000 0000 0000 0000 0101
//因为符号位是0,是正数,所以原码反码补码都相同,101就等于5
printf("%d\n",c);// 5
return 0 ;
}
他按照每一位来进行运算,相同则这一位的结果为0,不同 这一位的结果为1.这就是按位异或的计算思想
学了按位异或,我们来用按位异或解答一道题
题目:给定两个数字分别用a和b来接收,在不创建第三方变量的情况下,交换两个数字。
如果我们能创建第三方变量,那就非常简单,关键就是不能创建第三方变量。这里我们就能很巧妙的运用到异或操作符
我们先来看代码
int main()
{
int a = 10;
int b = 20;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d \nb = %d\n", a, b);
return 0;
}
运行结果如下
他是怎么实现交换的呢?我们来详细分析
为了方便我们只取8个字节来讲解 前面的都是0对结果不影响
a ^ b
a(10)二进制:0000 1010
b(20)二进制:0001 0100
a = a ^ b : 0001 1110
这时候a里面存放的就是(0001 1110)不再是10的二进制位了
a :0001 1110
b :0001 0100
b = a ^ b :0000 1010
这个时候把得出来的结果(0000 1010)存入到b当中,
就能发现这个结果其实就是原来的a,这里就完成了把
a的值给b这一步
接着 a :0001 1110
b :0000 1010
a = a ^ b :0001 0100
把得出来的结果(0001 0100)放入a当中,对比上面刚开始的b,
就是这个二进制位
这样一来就完成了a和b的交换
想必第一次见到的会感到特别神奇,就好像博主刚开始学习c语言接触到异或一样,这就是异或的魅力
但是为什么这么神奇呢?我再带大家换一种思路来解答
我们先来想一下
- 0^a = ?
- a^a = ?
int a = 10;
0 ^ a
0的二进制 :0000 0000
a的二进制(10):0000 1010
^ : 0000 1010
就等于a,所以我们得出结论:0和任何一个值异或(^)结果
都是本身
int a = 10;
a ^ a
a的二进制 :0000 1010
0000 1010
0000 0000
很显然,两个相同的值异或(^)结果等于0;
我们搞清楚了上面的两个特殊的关系,再来看原先的代码
int main()
{
int a = 10;
int b = 20;
a = a ^ b;
b = a ^ b;
//等号右边的a 相当于是a ^ b 所以可以写成
//b = a ^ b ^ b;两个b异或等于0,0再去跟a
//异或就等于a,这样就能很好地解释第二个表达式
a = a ^ b;
//同理,这里的b = a,所以表达式可以写成 a = a ^ b ^ a;
//同样能得到a = b 所以就完成了交换。
printf("a = %d \nb = %d\n", a, b);
return 0;
}
从上面也能看得出,异或(^)是满足交换律的。
当我们从上面这种直观的解释理解之后,我们再换一个角度
a = 10;
b = 20;
a ^ b
0000 1010
0001 0100
0001 1110
a = a ^ b;
//我们第一次求出来的a(0001 1110),其实可以当作一个密码子,
//当我们用b去异或这个密码子的时候,他会得到a,如果用a去异或这
//这个密码子,他会得到b
b = a ^ b;
a = a ^ b;
上面的例子我们得出结论,一个数,在异或运算当中,异或两次得出的结果,是参与异或运算的其他数的异或结果
我们通过这个结论,就可以很好的排除,数组当中两个重复的数字
例如下面的一道OJ题
消失的数字
我们就可以用异或来解答,会非常的简单,我们只需要把数组当中所有的数字全部异或一遍,之后再生成1-n的数字,再次异或,最后得出来的,就是缺失的数字。