2017做啥网站能致富,网页设计基础课心得体会2000字,网站开发一般会用到什么语言,徐州地产开发公司国企目录 
1、前言 
2、基本准则定律 
3、妙用归纳 
4、总结 1、前言 C语言中异或运算符^作为一个基本的逻辑运算符#xff0c;相信大家都知道其概念#xff1a;通过对两个相同长度的二进制数进行逐位比较#xff0c;若对应位的值不同#xff0c;结果为 1, 否则结果为 0。 但是…目录 
1、前言 
2、基本准则定律 
3、妙用归纳 
4、总结 1、前言 C语言中异或运算符^作为一个基本的逻辑运算符相信大家都知道其概念通过对两个相同长度的二进制数进行逐位比较若对应位的值不同结果为 1, 否则结果为 0。 但是它在实际使用中到底会有哪些应用场景或者说是有在一些编程技巧中该如何使用本文总结归纳了一些异或运算符的编程时实用方法思路以供参考如有其它好用的功能也可提出一起分享。 2、基本准则定律 首先需要明确的是异或运算的几个基本准则定律这些准则定律为异或运算的巧妙应用提供了基础。 交换律对于任意变量 a 和 ba ^ b 等于 b ^ a。  结合律对于任意变量 a、b 和 c(a ^ b) ^ c 等于 a ^ (b ^ c)。  自反性任何数与自身进行异或操作结果为0即 a ^ a  0。  零元素性质任何数与0进行异或操作结果为自身即 a ^ 0  a。  分配律a ^ (b  c)  (a ^ b)  (a ^ c)其中  表示按位与操作。  奇偶性一个数字和1做异或运算可以判断它的奇偶性。如果结果为0表示这个数字是偶数如果结果为1表示这个数字是奇数。  3、妙用归纳 暂归纳了10种在编程中经常遇见的异或运算使用的方法。 
1两个值的快速比较 例如比较两个值是否相等时一般我们使用这个 ab如果两个数相等 a ^ b 的结果为零。 
if(a^b  0) {//a和b若相同则为true 
} 
2数据交换 利用异或运算的性质可以进行两个数的交换不会利用额外的变量。 
void swap()
{ aa^b;bb^a;ab^a;
} 注意利用异或运算进行数据交换有个前提要交换的两个数必须在在不同的内存不然会出现问题。如果 a 和 b 是同一个地址呢比如我们调用的是 swap(a[i], a[j])当 i  j时利用异或运算进行数据交换是错误的。 在这种情况下我们第一步做的 a ^ b实际上就是 a[i] ^ a[i]。这将直接让a[i]中的元素等于0而丢失原本存在a[i]中的元素。后续这个元素就再也找不回来了。针对这个问题解决方案是在做这个交换之前判断一下 a 和 b的地址是否相同。也可以把逻辑改变为判断一下a和b是否相同。如果相同则什么都不做。 
3加减法 如二进制加法01  01  10而异或运算是01 ^ 01  00它其实做了加法但高位不进位所以异或又称不进位加法。 如二进制减法10 - 01  01而异或运算是10 ^ 01  11也可以看做个位0向高位借了一个1当2来用但高位不减1所以异或也可以称为不退位减法。 利用异或的这个特性只要再解决一下进位和退位问题就可以实现加减法了。这也是为什么CPU里面都是做位运算的逻辑门电路却能实现数值计算。 
int plus(int a, int b) {int sum, addition;while (b ! 0) {// 加法(未考虑进位)sum  a ^ b;// 进位值二进制中1  1的场景才会进位//a  b只有两个都为1结果才是1左移一位就是进位值了addition  (a  b)  1;// 赋值下次循环将进位加到a里面来直到进位等于0a  sum;b  addition;}return a;
}int subtraction(int a, int b){int sum, abdication;while (b ! 0){// 减法(未考虑退位)sum  a ^ b;// 退位值二进制中0 - 1的场景才会退位//~a  b只有a0,b1结果才是1左移一位就是退位值了abdication  (~a  b)  1;// 赋值下次循环将退位再从a中减掉直到退位等于0a  sum;b  abdication;}return a;
} 
4数据备份 使用异或也可以很容易实现多个数据的互相备份假如有数据a、b、c则d  a ^ b ^ c然后把数据d备份下来。 
当a丢失时可使用d ^ b ^ c来恢复
当b丢失时可使用d ^ a ^ c来恢复
当c丢失时可使用d ^ a ^ b来恢复 由此可见备份了一份数据d后丢失了其他任何一个数据都可以通过备份数据与其它数据异或恢复回来磁盘阵列技术raid5的数据备份原理用的就是这个特性。 
5数据加解密 在例如通信时需要对数据使用简单的加解密方法时使用异或操作可以进行明文数据的加解密。比如明文数据是message密钥是key加密后的数据是secret确保通信发送方和通信接收方都存储了相同的keykey可以使用rand()生产一串随机数则举例说明 
// 加密
secret  message ^ key
0x2C0E  0x89AB ^ 0xA5A5
// 解密
message  secret ^ key
0x89AB  0x2C0E ^ 0xA5A5 美国数学家香农证明了只要满足以下两个条件异或加密是无法破解的。 key的长度大于等于message。  key必须是一次性的且每次都要随机产生。  理由很简单如果每次的 key 都是随机的那么产生的secret具有所有可能的值而且是均匀分布无法从secret看出 message 的任何特征。也就是说它具有最大的信息熵因此完全不可能破解。这被称为异或的完美保密性。为了让异或加密更可靠可以添加一些其他操作例如对数据进行循环位移或取反的操作。 
6数据奇偶数判断 由于异或运算要先转化为二进制数而偶数的二进制数的最后一位必定是0奇数的二进制数的最后一位必定是1。 因此要判断的数与1异或得到的结果 - 要判断的数1说明该数是偶数反之是奇数 
int a  12345; //a123456
if ((a ^ 1) - a  1) {是偶数;
} else {是奇数;
} 
7出现奇偶次的找数问题 一个数组中有一种数出现了奇数次其他数都出现了偶数次怎么找到这一个数 分析利用异或性质a ^ a0则出现偶数的数字相异或为0而出现奇数次的异或结果为本身那么将所有的数异或后就是要找的这个出现奇数次的数。 
int ReOddNum1(int arr[], int len)
{int re  arr[0];for (int i1;ilen;i){re  arr[i] ^ re;}return re;
} 一个数组中有两种数出现了奇数次其他数都出现了偶数次怎么找到这两个数 step1将所有数异或得到rea^b step2提取re最右侧的“1”取反1自身相与 step3将所有该位为“1”的数相异或得到的数便为a或者b step4再次相与两个结果得到另一个数。 
int* ReOddNum2(int arr[], int len)
{int re  arr[0];int rr[2]  { 0,0 };//第一步将所有数异或得到a^bfor (int i  1; i  len; i){re  arr[i] ^ re;}//第二步提取re最右侧的“1”取反1自身相与int rightone  re(~re  1);//第三步将所有该位为“1”的数相异或得到的数便为a或者bint re1  0;for (int i  0; i  len; i){if ((arr[i]rightone)!0){re1  arr[i] ^ re1;}    }rr[0]  re1;//第四步再次相与两个结果得到另一个数rr[1]  re1^re;return rr;  
} 
8奇偶校验 首先先看一个例子理解下判断一个二进制数中1的数量是奇数还是偶数。 求10110101中出现1的数量是奇数还是偶数可将10110101逐位异或操作结果为1就是奇数个1结果为0就是偶数个1。 奇校验原始码1位校验位总共有奇数个1 偶校验原始码1位校验位总共有偶数个1。 比如为原始码添加奇偶校验位 原始码1101010 判断1的个数是否为偶数1^1^0^1^0^1^00因为逐位异或的结果为0所以1的个数为偶数奇校验则在原数据末尾添1变成11010101偶校验则在原数据末尾添0变成11010100。 
9对某些特定的位翻转 由于不管是0或者1与1做异或操作后将得到原值的相反值因此当我们需要翻转一个整数的某些位时我们可以使用位异或运算来实现掩码操作将对应的数据位进行翻转。 
//定义一个整数n
int a  0x0f; //二进制表示为00001111
//如果需要翻转a的第4和第5位则定义掩码mask
int mask  0x18; //二进制表示为00011000
//使用位异或运算翻转n的第3位和第4位
n  n ^ mask; //结果为二进制表示为00010111 在单片机编程中对GPIO输出控制LED的闪烁原理也是如此定义了一个宏直接通过GPIOA口对ODR寄存器进行操作异或PIN2的位。实现引脚PA2输出高低电平的翻转控制LED闪烁。 
// PA2引脚输出电平翻转
#define LED_TOGGLE() GPIOA-ODR ^ GPIO_PIN_2 
10数据符号判断 例如判断两个int32类型的数据的符号是否相同其中31是符号位的偏移量 
if (((a ^ b)  31)  1) {符号不相同;
} else {符号相同;
} 4、总结 总之异或运算是一种重要的二进制运算在实际代码编程中有着广泛的应用。需要深刻的去理解异或运算符的几条基本准则定律就能够快速地完成数字的交换、计算、去重等操作为我们在功能开发中提供便利。 小tips归根到底在布尔代数中其实只需要与、或、非运算就可以实现所有其它运算所以异或运算实际可以通过与、或、非实现最直观的表示方式如下 
a ^ b  (~a  b) | (a  ~b)   ↓↓↓更多技术内容和书籍资料获取入群技术交流敬请关注“明解嵌入式”↓↓↓