## 位运算符 - 程序中的所有数据在计算机内存中都是以二进制的形式储存的。 - 位运算就是直接对整数在内存中的二进制位进行操作 - C语言提供了6个位操作运算符, 这些运算符只能用于整型操作数 | 符号 | 名称 | 运算结果 | | ---- | -------- | ------------ | | & | 按位与 | 同1为1 | | \| | 按位或 | 有1为1 | | ^ | 按位异或 | 不同为1 | | ~ | 按位取反 | 0变1,1变0 | | << | 按位左移 | 乘以2的n次方 | | >> | 按位右移 | 除以2的n次方 | ------ - 按位与: - 只有对应的两个二进位均为1时,结果位才为1,否则为0 - 规律: 二进制中,与1相&就保持原位,与0相&就为0 ``` 9&5 = 1 1001 &0101 ------ 0001 ``` ------ - 按位或: - 只要对应的二个二进位有一个为1时,结果位就为1,否则为0 ```c 9|5 = 13 1001 |0101 ------ 1101 ``` ------ - 按位异或 - 当对应的二进位相异(不相同)时,结果为1,否则为0 - 规律: - 相同整数相的结果是0。比如55=0 - 多个整数相^的结果跟顺序无关。例如: 567=576 - 同一个数异或另外一个数两次, 结果还是那个数。例如: 577 = 5 ```c 9^5 = 12 1001 ^0101 ------ 1100 ``` ------ - 按位取反 - 各二进位进行取反(0变1,1变0) ```c ~9 =-10 0000 0000 0000 0000 0000 1001 // 取反前 1111 1111 1111 1111 1111 0110 // 取反后 // 根据负数补码得出结果 1111 1111 1111 1111 1111 0110 // 补码 1111 1111 1111 1111 1111 0101 // 反码 1000 0000 0000 0000 0000 1010 // 源码 == -10 ``` ------ - 位运算应用场景: - 判断奇偶(按位或) ```c 偶数: 的二进制是以0结尾 8 -> 1000 10 -> 1010 奇数: 的二进制是以1结尾 9 -> 1001 11 -> 1011 任何数和1进行&操作,得到这个数的最低位 1000 &0001 ----- 0000 // 结果为0, 代表是偶数 1011 &0001 ----- 0001 // 结果为1, 代表是奇数 ``` - 权限系统 ```c enum Unix { S_IRUSR = 256,// 100000000 用户可读 S_IWUSR = 128,// 10000000 用户可写 S_IXUSR = 64,// 1000000 用户可执行 S_IRGRP = 32,// 100000 组可读 S_IWGRP = 16,// 10000 组可写 S_IXGRP = 8,// 1000 组可执行 S_IROTH = 4,// 100 其它可读 S_IWOTH = 2,// 10 其它可写 S_IXOTH = 1 // 1 其它可执行 }; // 假设设置用户权限为可读可写 printf("%d\n", S_IRUSR | S_IWUSR); // 384 // 110000000 ``` - 交换两个数的值(按位异或) ```c a = a^b; b = b^a; a = a^b; ``` ------ - 按位左移 - 把整数a的各二进位全部左移n位,高位丢弃,低位补0 - 由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性 - 规律: 左移n位其实就是乘以2的n次方 ```c 2<<1; //相当于 2 *= 2 // 4 0010 <<0100 2<<2; //相当于 2 *= 2^2; // 8 0010 <<1000 ``` - 按位右移 - 把整数a的各二进位全部右移n位,保持符号位不变 - 为正数时, 符号位为0,最高位补0 - 为负数时,符号位为1,最高位是补0或是补1(取决于编译系统的规定) - 规律: 快速计算一个数除以2的n次方 ```c 2>>1; //相当于 2 /= 2 // 1 0010 >>0001 4>>2; //相当于 4 /= 2^2 // 1 0100 >>0001 ``` - 练习: - 写一个函数把一个10进制数按照二进制格式输出 ```c #include void printBinary(int num); int main(int argc, const char * argv[]) { printBinary(13); } void printBinary(int num){ int len = sizeof(int)*8; int temp; for (int i=0; i>(31-i); //每次移动的位数 int t = temp&1; //取出最后一位 if(i!=0&&i%4==0)printf(" "); printf("%d",t); } } ``` ## 最后,如果有任何疑问,请加微信 **leader_fengy** 拉你进学习交流群。 开源不易,码字不易,如果觉得有价值,欢迎分享支持。