目录
位运算
位运算和逻辑运算区别
位运算是一位对应一位的对所有位逐一进行运算(逐比特位进行运算).逻辑运算是以计算表达式的真假为主进行运算.
位运算的几点注意
- 呆板都是使用补码进行运算,遇到负数时不要混淆
- ~(-1)的结果是0,~(0)的结果是-1,按位取反所有位都要取反,不论是否有符号.
异或的运算规则
- 运算规则: 雷同为假, 相异为真
- 0000 0000 ... 0100
- 0000 0000 ... 0011
复制代码 0000 0000 ... 0111
printf("%d\n",4^3); //结果:7- 2. 任何数据和0异或,结果都是它本身
- ```C
- printf("%d\n",1 ^ 0); //结果:1
- printf("%d\n",6 ^ 0); //结果:6
- printf("%d\n",7 ^ 0); //结果:7
- printf("%d\n",-1 ^ 0); //结果:-1
复制代码
- 异或运算支持交换律和结合律
- printf("%d\n",5 ^ 5 ^ 4); //结果:4
- printf("%d\n",5 ^ 4 ^ 5); //结果:4 => 交换律
- printf("%d\n",5 ^ (5 ^ 4)); //结果:4 => 结合律
复制代码 - 异或自己的结果是0 (消消乐)
异或的经典问题:两数交换
问题:两个变量int a = 10; int b = 20;再不使用第三个变量的前提下,怎么讲两个数进行交换?
方法一:加减法- a = a + b; // ①
- b = a - b; // ②
- a = a - b; // ③
复制代码 解析:
(在计算机运算中,运算过程可以当作第三个变量,只是这个过程必须赋值才有意义,我们可以计算出各种组合的值用来匹配和验证)
- ①是将a和b的值生存到a中.原理:a+b-b = a,只要b还在,a就不会丢失.(借助a当作第三个容器)
- ②:验证发现新a-b = 旧a,赋值给b后就能实现b变成了旧a.
- ③:a变量生存着旧a和旧b,新b生存旧a,于是新a-新b就等于旧b.
缺点: 加法大概会有比特位递增,如果发生溢出,则会发生截断,导致数据丢失.所以这种方法仅适用于一定范围的数据
方法二:异或法- a = a ^ b; //①
- b = a ^ b; //②
- a = a ^ b; //③
- 一次记住它: 等号左边是aba,右边全是a^b
复制代码 解析 消消乐)
- ①是a和b的值生存在a中.原理:a^b^b=a,只要b还在a就不会丢失.
- ②: 新a=10^20,对b=a^b=10^20^20,利用结合律,先计算20^20,就可以得到a,然后再赋值给b,b变量就得到了旧a的值.
- ③:有了旧a的值,交换律+消消乐把新a中旧a的值消掉,新a就可以得到旧b的值,完成交换.
相对于加减法的优点: 异或不会进位,不会出现比特位递增、溢出的问题
位操作建议使用宏定义好后使用
[code]// 0|0 = 0 ; 0|1 = 1 // 规律:任何数或0结果都是它自己 //用途:// 1|0 = 1 ; 1|1 = 1 // 规律:任何数或1,结果都是被设置为1 //用途:特定 比特位 置1// 组适用途:让特定比特位置1,其他位不变// 0&0 = 0 ; 0&1 = 0; // 规律:任何书与0,结果都是被设置成0 //用途:特定比特位置0// 1&0 = 0 ; 1&1 = 1; // 规律:任何书与1,结果都是它自己 //用途:获取特定比特位的值// 组适用途:没有干扰地获取特定比特位的值//一般都是用1(000...1)比较方便,通过移动1的位置,加上差别的位运算符,能够实现差别的功能.#define SETBIT(x,n) (x |= (1 |