1、位运算符

程序中的所有数据在计算机内存中都是以二进制的形式储存的。

位运算就是直接对整数在内存中的二进制位进行操作

C语言提供了6个位操作运算符, 这些运算符只能用于整型操作数

符号

名称

运算结果

&

按位与

同1为1

|

按位或

有1为1

^

按位异或

不同为1

~

按位取反

0变1,1变0

<<

按位左移

乘以2的n次方

>>

按位右移

除以2的n次方

(1)按位与:

只有对应的两个二进位均为1时,结果位才为1,否则为0

规律: 二进制中,与1相&就保持原位,与0相&就为0

 9&5 = 1

  1001
 &0101
 ------
  0001

(2)按位或:

只要对应的二个二进位有一个为1时,结果位就为1,否则为0

 9|5 = 13

  1001
 |0101
 ------
  1101

(3)按位异或

当对应的二进位相异(不相同)时,结果为1,否则为0

规律:

相同整数相的结果是0。比如55=0

多个整数相^的结果跟顺序无关。例如: 567=576

同一个数异或另外一个数两次, 结果还是那个数。例如: 577 = 5

 9^5 = 12

  1001
 ^0101
 ------
  1100

(4)按位取反

各二进位进行取反(0变1,1变0)

 ~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

2、位运算应用场景

(1)判断奇偶(按位或)

    偶数: 的二进制是以0结尾
    8   -> 1000
    10  -> 1010
    
    奇数: 的二进制是以1结尾
    9   -> 1001
    11  -> 1011

    任何数和1进行&操作,得到这个数的最低位
    1000
   &0001
    -----
    0000  // 结果为0, 代表是偶数

    1011
   &0001
    -----
    0001 // 结果为1, 代表是奇数

 (2)权限系统

   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

 (3)交换两个数的值(按位异或)

  a = a^b;
  b = b^a;
  a = a^b;

 (4)按位左移

把整数a的各二进位全部左移n位,高位丢弃,低位补0

由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性

规律: 左移n位其实就是乘以2的n次方

 2<<1; //相当于 2 *= 2 // 4
   0010
 <<0100

 2<<2; //相当于 2 *= 2^2; // 8
   0010
 <<1000

 (5)按位右移

把整数a的各二进位全部右移n位,保持符号位不变

为正数时, 符号位为0,最高位补0

为负数时,符号位为1,最高位是补0或是补1(取决于编译系统的规定)

规律: 快速计算一个数除以2的n次方

 2>>1; //相当于 2 /= 2 // 1
   0010
 >>0001
 4>>2; //相当于 4 /= 2^2 // 1
   0100
 >>0001

 

3、练习:

(1)写一个函数把一个10进制数按照二进制格式输出

 #include <stdio.h>
 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<len; i++) {
         temp = num; //每次都在原数的基础上进行移位运算
         temp = temp>>(31-i); //每次移动的位数
         int t = temp&1; //取出最后一位
         if(i!=0&&i%4==0)printf(" "); printf("%d",t);
     }
 }