位运算在嵌入中也是一个重要的点,下面就简单介绍和举一些有用的例子,如果有不足的话,请补充,废话不多说,直接开始!


位运算操作符有6个:&,|,^,~,>>,<<

        &   只有1&1才等于1,其它都为0

        |   只有0|0才等于0,其它都为1

        ^   异或,相异为1,相同为0,用来检查两个操作数的某对应位是否一致 

        ~   非,按位反,任何数的非与数本身相加都等于-1(如果不懂的话,请查看下一篇补码)

        >>  左移,相当乘以2-->左移之后,后面补零

        <<  右移,相当除以2-->右移之后,对于无符号数,相应位补零,有符号数,最高位不变,其它补零

        移位操作主要对外部设备的输入解码,读取信息,或者是加密

j_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gifj_0057.gif

note:

1.c是专门为多数程序设计中取代汇编语言而设计的,所以c支持许多汇编操作

2.左移并不能恢复右移丢失的信息

3.一般只对unsigned int ,int ,unsigned char ,char 进行位操作,不能对浮点进行位操作!!!

4.1)左移例子:7(10)-->111(2),7左移2位,7<<2 -->111<<2-->11100-->28(10)   ==>7*2^2=28

  2)右移例子:7(10)-->111(2),7右移2位,7>>2 -->111>>2-->001-->1(10)   ==>7/2^2=1  (取整数)

5.非即是数本身的相反数据的没有加上1的补码(补码本来要加1),所以和本身相加为-1

eg:

  1 #include <stdio.h>
  2 int main()
  3 {
  4         int i = 10;     //1010
  5         int j = 7;      //0111
  6         int ret = 0;    //0  区别逻辑运算的&&和||,它们的值只能是0或1,位运算就是普通数值
  7 
  8         ret = i & j;    //0010  1&1=1,其它为0
  9         printf("ret is %d\n",ret);//2
 10 
 11         ret = i | j;    //1111  0|0 =0,其它为1
 12         printf("ret is %d\n",ret);//15
 13 
 14         ret = i << 2;   //101000  右边补零
 15         printf("ret is %d\n",ret);//40
 16 
 17         ret = i >> 2;   //0010 2 左边补零
 18         printf("ret is %d\n",ret);//2
 19 
 20         ret = i ^ j;    //异或 不同为1,其它为零 1101 --13
 21         printf("ret is %d\n",ret);//13
 22 
 23         ret = ~i;       //非(按位取反)任何的数的非与本身相加都等于-1,eg i->1010 ,j->0101 
 24         //非即是数本身的相反数据的没有加上1的补码(补码本来要加1),所以和本身相加为-1;
 25         printf("ret is %d\n",ret);//-1
 26 }

wKiom1RQfRmQKQt7AAA2ckk6nfw299.jpg



功能:将第n位变为0/1,其它位不变

注意:将第一位称为第0位!

        将第n位变为0:a & ~(1<<n)
        eg:unsigned int i = 0x9f43bda5;
              int ret = 0; 
                //将第2位变为0
              ret = i & ~(1<<2);
        
        将第n位变为1:a | (1<<n)
        eg:unsigned int i = 0x9f43bda5;
              int ret = 0;
             //将第3位变为1
              ret = i | (1 << 3);

扩展:将某些连续位变为0/1,其它位不变

方法:先计算连续位全1是多少再移位

        //将第4-9位变为1   (4-9共6位,全1-->3f)
        ret = i |(3f << 4);
        //将第3-7位变为0
        ret = i & ~(1f << 3);
        //将第1-6位和9-12位变为1
        ret = i |(f3f << 1);
 
        //将第2-8位和13-20位变为0
        ret = i & ~(7f << 2) & ~(ff << 13);


eg:
  1 #include <stdio.h>
  2 int main()
  3 {
  4         unsigned int i = 0x9f43bda5;
  5         int ret = 0; 
  6         //将第3位变为1
  7         ret = i | (1 << 3);
  8         printf("ret is %x\n",ret);
  9         
 10         //将第2位变为0
 11         ret = i & ~(1<<2);
 12         printf("ret is %x\n",ret);
 13         
 14         //将第4-9位变为1
 15         ret = i | (0x3f << 4);
 16         printf("ret is %x\n",ret);
 17         
 18         //将第3-7位变为0
 19         ret = i & ~(0x1f << 3);
 20         printf("ret is %x\n",ret);
 21         
 22         //将第1-6位和9-12位变为1
 23         ret = i |(0xf3f << 0);
 24         printf("ret is %x\n",ret);
 25         
 26         //将第2-8位和13-20位变为0
 27         ret = i & ~(0x7f << 2) & ~(0xff << 13);
 28         printf("ret is %x\n",ret);
 29 }

wKiom1RQfzjABMLwAACGuiYsD2I764.jpg