C语言拾遗--位运算

 

C语言中的位运算符及应用

位逻辑运算符:&(位“与”)、^(位“异或”)、|(位“或”)、~(位“取反”)。

位逻辑运算以位(bit)为单位,1个字节有8个位,每个位有01两个取值。1 B = 8 bits

 

位取反操作

位取反的操作符为“~”,0变成11变成0,需要注意的是,位取反运算并不改变操作数的值。在 嵌入式开发中,改变led灯的亮灭常用取反操作符。取反示例:

unsigned char led=15;              //00001111

printf(“%d”,~led);                    //11110000           240

 

位与运算

位与运算的操作符为&1 & 1=1   1 & 0=0    0 & 1=0    0 & 0=0;

0相与结果都为0,与1相与值不变,常用于清零操作。

位与也可以实现取出指定位。位与运算示例:

unsigned char led = 3;               //00000011

unsigned char yu=240;             //11110000

printf(“%d”,led&yu);               //00000000          结果为0

与运算高级用法

1将末位清零

#include <stdio.h>

int main(void) {

   int  led =15;      //0000 1111

   led=led&~1;      //~1=1111 1110 

                      // 00001110

   printf("%d",led);

          return 0;

}

2不用%求余数,如求154整除的余数,对4整除,一般用于结构体字节对齐,便于内存对齐。

#include<stdlib.h>

int main(void) {

   int  led =15;      //0000 1111

   led=led-( led&~3);     //( led&~3)  抹除后两位,就能整出4,再相减即可得

                 

   printf("%d",led);

          return 0;

}

3.统计二进制整数有多少个1   x&x-1,每次减少一个1

#include<stdlib.h>

int main(void) {

  int x=250;       //1111 1010

 

    int i=0;

    while(x)

    {

        i++;

        x=x&(x-1);

    }

      printf("%d   ",i);

            return 0;

}

 

位或运算

位或运算的操作符为|,将对两个操作数的每一位进行或运算,位“或”运算的准则如下:

1 | 1=1      1 | 0=1      0 | 1=1      0 | 0=0

1相或都为1,可以让某些位变为1

unsigned char led = 3;               //00000011

unsigned char huo=240;           //11110000

printf(“%d”,led|huo);                //1111 0011          结果为0     243

 

异或运算

位异或运算的操作符为^,将对两个操作数的每一位进行异或运算。通俗地讲,如果位“异或”运算的两个位相同(同为0或同为1),结果为0,若两个位不同(一个为0,另一个为1),结果为1,对应的准则为:

1 ^ 1=0  1 ^ 0=1  0 ^ 1=1 0 ^ 0=0

无论是0还是1    1 进行异或都会进行逆转实现反转

无论是0还是1   0进行异或都不会发生变化

异或运算示例:

unsigned char led =169;                   //10101001

unsigned char yihuo=15;                  //00001111

printf(“%d”,led^yihuo);                   //10100110          166

异或交换两个变量,不借助中间变量

#include <stdio.h>

int main(void) {

  unsigned char led =15;          //0000 1111

  unsigned char yihuo=240;        //1111 0000

   led=led^yihuo;

  yihuo=led^yihuo;

  led=led^yihuo;

  printf("%d,%d",led,yihuo);     //240,15

            return0;

}

原理同下数学技巧,不过下面这种会有溢出的风险

#include <stdio.h>

int main(void) {

   int led =15;          

   int yihuo=240;      

   led = led+yihuo;

   yihuo=led-yihuo;

   led=led-yihuo;

   printf("%d,%d",led,yihuo);

            return 0;

}

移位运算

顾名思义,移位运算就是将某个量中的bits向左或向右移动,该量的值也会相应发生变化,在开灯关灯这个场景中,移位运算的一个重要应用是实现流水灯效果,即按从18或从81的顺序每次只亮一个灯。

移位运算符:<<(左移)、>>(右移)

 

1. 移位运算就是将某个量中的bits向左或向右移动,该量的值也会相应发生变化。

移位运算表达式的基本形式为:

A << n;                  /*左移*/

A >> n;                  /*右移*/

A称为操作数,其必须为数字型变量或数字型常量,此处的数字型包括整型、浮点型和char型,A中存储的01序列向左或右移动n位,移动后的值作为整个表达式的输出,执行移位运算并不改变操作数A的值。

2. 左移,左移一位等价于乘2,右边填充为0

#include <stdio.h>

#include<stdlib.h>

int main(void) {

  unsigned char ch=1;       //0000 0001

  for(int i=0;i<8;i++)      //char  类型占一个字节共有八位

  {

      ch=ch<<1;                //通过赋值改变操作数

      printf("%d   ",ch); 

}

          return 0;

}

结果为:2   4   8   16  32   64   128  0  

只有8位,只能移动7位,多了溢出为 1 00000000 ,取后八位,为0

 

3. 右移,右移一位等价于除以2,按照符号位,正数左边填充0,,负数填充1

#include <stdio.h>

#include<stdlib.h>

int main(void) {

  unsigned char ch=128;       //1000 0000

  for(int i=0;i<7;i++)     

  {

      ch=ch>>1;                //移位操作在寄存器中进行,要改变需要赋值

      printf("%d   ",ch);

  }

          return 0;

}

结果为64   32  16   8   4  2   1  

 

移位应用

//打印 补码 

#include <stdio.h>

int main(void) {

  int  num=-1;      //

    int data=1<<31;

    for (inti=1;i<=32;i++)

    {

       printf("%c",(num&data ?'1':'0'));

        num<<=1;

        if(i%4==0)

        {

          printf(" "); 

        }

    }

            return 0;

}

结果为     1111 1111 11111111 1111 1111 1111 1111

 

位运算输出浮点数据

#include <stdio.h>

int main(void) {

  float num=1.5;       //

  unsigned char *p=(unsigned char*)&num;//进行地址转换 ,共享内存

    for (int i=3;i>=0;i--)

    {

      unsigned char chs=p[i];

      for(int j=7;j>=0;j--)

      {

          if(chs&(1<<j))

          {

              printf("1");

          }

          else

          {

              printf("0");

          }

      }

      printf("  ");

    }

            return 0;

}

结果为 00111111  11000000 00000000  00000000 

 

注意事项

1.    位运算仅仅适用于整数,字符,实数是指数方式表示的,不适用于位运算。

2.    无符号的数据在进行位运算的时候,需要自动进行转换,低字节向高字节转换的时候,会自动填充0

3.     有符号在进行位运算的时候,需要自动进行转换低字节向高字节转换的时候,正数会按照符号位0 会自动填充0,负数会按照符号位1  自动填充1.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值