聊聊位运算一些注意事项
目录[*]位运算
[*]位运算和逻辑运算区别
[*]位运算的几点注意
[*]异或的运算规则
[*]异或的经典问题:两数交换
[*]位操作建议使用宏定义好后使用
[*]位运算整型提拔问题
[*]左移和右移
[*]概念
[*]移位运算轻易误解成移位赋值
位运算
位运算和逻辑运算区别
位运算是一位对应一位的对所有位逐一进行运算(逐比特位进行运算).逻辑运算是以计算表达式的真假为主进行运算.
位运算的几点注意
[*]呆板都是使用补码进行运算,遇到负数时不要混淆
[*]~(-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的值,完成交换.
相对于加减法的优点: 异或不会进位,不会出现比特位递增、溢出的问题
位操作建议使用宏定义好后使用
// 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
页:
[1]