目录
一、实现原理
1.定义
逻辑算符异或(exclusive or)是一种位运算,符号为 XOR 或 ⊕(编程语言中常用^)。但与一般的逻辑或不同,对于运算符左右两侧的运算元,对应的二进制位若相同,则该位取0,不同则该位取1,即按位异或(相同为0,不同为1)。(异或运算其实就是二进制下的不进位加法)
真值表
A B A^B 1 0 1 1 1 0 0 0 0 0 1 1
eg:若a为十进制下的10 b为十进制下的12
a转换为二进制为 1010
b转换为二进制为 1100
对应位置进行异或操作:a⊕b(a^b)= 0110 结果为6
可以看出,对应位置同为1或0,异或后均为0;对应位置为1和0时,异或后为1。
2.性质
a ⊕ a = 0 a ⊕ 0= a
a ⊕ b = b ⊕ a(交换律)
a ⊕b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c(结合律)
二、实现代码
1、代码
#include <stdio.h>
int main(){
int a = 10;
int b = 12;
//交换前的数字
printf("交换前a的值为:%d\n",a);
printf("交换前b的值为:%d\n",b);
//实现数字交换并输出
a = a ^ b;//现在a = a ^ b
b = a ^ b; //b = (a ^ b) ^ b = a ^ (b ^ b) =a
a = a ^ b;//a = (a ^ b) ^ a = b ^ (a ^ a) =b
printf("交换后a的值为:%d\n",a);
printf("交换后b的值为:%d\n",b);
}
运行结果:
交换前a的值为:10
交换前b的值为:12
交换后a的值为:12
交换后b的值为:10
2、使用注意事项(陷阱分析)
(1)相同数字异或可以完成交换数字吗?
#include <stdio.h>
int main(){
int a = 10;
int b = 10;
//交换前的数字
printf("交换前a的值为:%d\n",a);
printf("交换前b的值为:%d\n",b);
//实现数字交换并输出
a = a ^ b;//现在a = a ^ b
b = a ^ b; //b = (a ^ b) ^ b = a ^ (b ^ b) =a
a = a ^ b;//a = (a ^ b) ^ a = b ^ (a ^ a) =b
printf("交换后a的值为:%d\n",a);
printf("交换后b的值为:%d\n",b);
}
将上述b的值改为10,此时a与b的值均为10,会交换成功吗?
运行结果:
交换前a的值为:10
交换前b的值为:10
交换后a的值为:10
交换后b的值为:10可见,交换俩个相同的数时可以成功的。
(2)什么情况下使用异或进行交换会出现问题?
#include <stdio.h>
int main(){
int a = 10;
int b = 12;
//交换前的数字
printf("交换前a的值为:%d\n",a);
printf("交换前b的值为:%d\n",b);
b = a;
//实现数字交换并输出
a = a ^ b;//现在a = a ^ b
b = a ^ b; //b = (a ^ b) ^ b = a ^ (b ^ b) =a
a = a ^ b;//a = (a ^ b) ^ a = b ^ (a ^ a) =b
printf("交换后a的值为:%d\n",a);
printf("交换后b的值为:%d\n",b);
}
改造上面代码,将a赋值给b(a = b)
运行结果:
交换前a的值为:10
交换前b的值为:12
交换后a的值为:10
交换后b的值为:10可见,俩数交换结果出现问题,到底是什么原因导致的呢,下面进行分析。
在使用异或进行交换数字时
一定要保证俩数不指向同一地址!!!
一定要保证俩数不指向同一地址!!!
一定要保证俩数不指向同一地址!!!
当b指向与a同一地址时,a的值会将b本身的值进行覆盖,使得交换的俩数变为同一个数10。然后,就会遇到上述问题,使得俩数变为相同的数字。
包括数组交换过程中避免指向同一地址,否则会导致交换失败。