C语言位运算应用实例

C语言位运算应用实例这里写自定义目录标题 C 语言位运算应用实例一 位操作规则 1 与运算 amp 2 或运算 C 语言位运算应用实例正在准备 2019 年 RM 比赛 遇到这样一个场景 Tx2 图像采集之后要把目标位置传给 stm32 控制板 位置信息有 x y 这一属性 准备用串口做数据传输 传输数据范围是 0 560 且为整数 但是查了一下发现 stm32 的串口一次最多读 8 位数据 也就是 0 255 没有办法 只能把数

C语言位运算应用实例

正在准备2019年RM比赛,遇到这样一个场景:Tx2图像采集之后要把目标位置传给stm32控制板,位置信息有x/y这一属性,准备用串口做数据传输。

传输数据范围是[0,560]且为整数,但是查了一下发现stm32的串口一次最多读8位数据,也就是[0,255],没有办法,只能把数据拆成两个8位的来传输。

下面根据一应用实例总结C语言中位运算使用。


一、位操作规则

共有6种位操作

运算符 含义
& 按位与运算
i 按位或运算
^ 按位异或运算
~ 按位取反运算
<< 左移
>> 右移
  • 按位运算:指把参与运算的两个数据都换位二进制后,每两个对应位进行运算并得到新二进制数*
  • 若把存储运算结果的变量设为unsigned类型,则所有位都是数据位;否则以补码形式换算为带符号十进制数。
  • 以下都是以unsigned型为例

1、与 (&)

运算 结果
0 & 0 0
0 & 1 0
1 & 0 0
1 & 1 1

规则:有0为0,全1为1

1、实例:

  • 3&5 = 011 & 101 = 001=1

2、常用用法:

  • 对某些位清零。如要对3:0位清零,只需将数据与1111 0000 &运算即可
  • 取数据中某些位。如取0110 0110中2:1位,(0110 0110 & 0000 0110>>1=11=3

2、或 (|)

运算 结果
0 0
0 1
1 0
1 1

规则:有1为1,全0为0

1、实例:

  • 3|5 = 011 | 101 = 111=7

2、常用用法:

  • 对某些位赋值。如给0111 0000的3:0位赋1111:0111 0000|0000 1111 =0111 1111

3、与或 (^)

运算 结果
0 ^ 0 0
0 ^ 1 1
1 ^ 0 1
1 ^ 1 0

规则:相同为0,不同为1

1、实例:

  • 3^5 = 011 ^ 101 = 110 = 6

2、常用用法:

  • 使特定位翻转。将要翻转的位与1异或运算,如翻转1010的1:0位:1010^0011=1001

4、取反 (~)

运算 结果
~0 1
~1 0

规则:1变0,0变1

1、实例:

  • ~3 = ~011 = 100 = 4

2、常用用法:

  • 使全部位翻转

5、左移、右移(<< 、>>)

运算 结果
a<
把数据a左移n位(换成二进制形式移),溢出部分舍去,末尾补0
a>>n 把数据a右移n位(换成二进制形式移),移出末位部分舍去,高位补0

1、实例:

  • 3<<2 = 011<<2 = 01100 = 12
  • 3>>2 = 011>>2 = 0 = 0

2、常用用法:

  • 配合&运算把取出的位移到最低。
  • a<
  • a>>n == a/2^n

二、位操作应用实例

要处理文章开头提出的实际问题,设计数据传输格式为:

  • 每帧数据长8位,且表示正整数(unsigned char型)
  • 每两帧数据拼一个真实数据,最多表示12位 ( [0,4095] )
含义
7 指示x,y属性(1-x 0-y)
6 指示拼数据时高低属性(1-高 0-低)
5:0 数据

1、编码

思路:分别取数据 5:0 和 11:6 位域,根据数据属性补充最高两位数据。实例如下:

#include  
        using namespace std; #define DATA 1200 //待编码数据 #define Low 0 //用于补齐高位信息 #define High 1 #define X_ctrl 1 #define Y_ctrl 0 unsigned char set_flag_bit(unsigned char data,int X_Y,int H_L) //填高2位 { 
       data &= 0X3F; //高2位清零 0x3F=0011 1111  if(X_Y==Y_ctrl && H_L==Low) //Y-L 00 data |= 0X00; //0x00=0000 0000 else if(X_Y==X_ctrl && H_L==Low) //X-L 10 data |= 0X80; //0x80=1000 0000 else if(X_Y==Y_ctrl && H_L==High) //Y-H 01 data |= 0X40; //0x40=0100 0000 else if(X_Y==X_ctrl && H_L==High) //X-H 11 data |= 0XC0; //0xC0=1100 0000 return data; } unsigned char Ldata,Hdata; void data_processing(int data,int X_Y) { 
       Ldata=data & 0XFF;//取低8(1-8)位 0xFF = 1111 1111  Ldata=set_flag_bit(Ldata,X_Y,Low); Hdata=(data & 0X3FC0)>>6;//取高7-14位 0xFF = 1111 1111 0000 0000 Hdata=set_flag_bit(Hdata,X_Y,High); } int main() { 
       int data = DATA; data_processing(DATA,Y_ctrl); // cout< 
      
        cout 
       << 
       ( 
       unsigned 
       int 
       )Hdata 
       << 
       " " 
       << 
       ( 
       unsigned 
       int 
       )Ldata 
       <<endl 
       ; 
       return 
       0 
       ; 
       } 
      

2、解码

思路:先取数据高二位判断属性,根据其信息拼接数据并存入x、y数据buff中。实例如下:

#include 
        using namespace std; unsigned int x_real_data_buff[10];//存储x、y数据的buff,用于滑动平均滤波 unsigned int y_real_data_buff[10]; int x_real_data_cnt=0;//buff中数据个数计数 int y_real_data_cnt=0; unsigned char data_decode(unsigned char data) { 
       unsigned int real_data; static int x_cnt=0; static int y_cnt=0; static unsigned char Hdata; static unsigned char Ldata; static unsigned char update_flag=0;//标记是否已收到高段数据(是-1,不是-0) static float x_aver=0; static float y_aver=0; unsigned char X_Y_decide; //1->X unsigned char H_L_decide; //1->H switch((data & 0xc0)>>6)//0xc0=1100 0000,这里取高2位 { 
       case 0x00: //00  X_Y_decide=0; H_L_decide=0; Ldata=(data & 0X3F);//0X3F=0011 1111,这里取出该数据帧中有效数据部分 break; case 0x01: //01 X_Y_decide=0; H_L_decide=1,update_flag=1; Hdata=(data & 0X3F); break; case 0x02: //10 X_Y_decide=1; H_L_decide=0; Ldata=(data & 0X3F); break; case 0x03: //11 X_Y_decide=1; H_L_decide=1,update_flag=1; Hdata=(data & 0X3F); break; } if(update_flag==1 && H_L_decide==0//已收到高位,又收到低位,一个数据接收完成 { 
       update_flag=0; real_data=Hdata;//这里直接左移会溢出丢数据,所以应先给16位的real_data再左移 real_data=(real_data<<6) | Ldata; if(X_Y_decide==1) x_real_data_buff[x_real_data_cnt++]=real_data; else y_real_data_buff[y_real_data_cnt++]=real_data; } } void show_data(unsigned int *buff,int CNT) { 
       for(int i=0;i<CNT;i++) cout<<buff[i]<<" "; cout<<endl; } int main() { 
       unsigned char data_buff[]={ 
      0x52,0x30,0xd2,0xb0};//待解码数据写在这里 for(int i=0;i<sizeof(data_buff)/sizeof(data_buff[0]);i++) data_decode(data_buff[i]); cout<<"x_data:"; show_data(x_real_data_buff,x_real_data_cnt); cout<<"y_data:"; show_data(y_real_data_buff,y_real_data_cnt); return 0; } 
  • 经测试,上述代码可以稳定实现自定义数据协议的编码解码工作。
  • 抗传输丢包效果良好,除非恰好连续丢 “此数据低段” 和“下一数据高段” ,否则不会读取到错误信息。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/217245.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午10:01
下一篇 2026年3月18日 上午10:01


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号