位运算符&和>>配合给有位域的结构体赋值

简介: v位运算符&和>>配合给有位域的结构体赋值

在做通信协议处理的时候,接收到对端的数据,需要根据固定的结构去做解析。

在某些场景下,需要把字符按一定协议赋值给自己定义的结构体(涉及位域)

我的第一想法是直接强转指针或者按位拷贝,但不能适应所有场景。

可以通过位运算 使用位运算符& 和>> 实现数据的获取.

收获到的基础知识点:

把一个字符赋值给有位域相关的内存时,可以采用位运算符& 和 >> ,<<实现:

&: 提取到一个字节中,对应位置的对应值

>>和<< :由于结构体位域自定义了目标bit的位置,通过<<和>>可以实现

例如:

//& 如果对应位为1,则值为1,否则为0
  test->bit = c_test & 0x01;  //只取bit对应位的有效位  如果是在最高位  可以用0x80
  test->name = (c_test & 0xfe) >> 1;// & 1111 1110 取到name对应二进制位的所有的1,然后通过位移确定位置
  t_test1.name = c_test1 & 0x7f;  //c_test1 & 7f = 1001 0001 & 0111 1111 = 1 0001
  t_test1.bit = (c_test1 & 0x80) >> 7; //1001 0001 & 1000 0000 = 1000 0000 右移7位

测试demo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//这种定义 先地位  再高位 
typedef struct _t_strust_test
{
  unsigned char bit:1;
  unsigned char name:7;
}STRUCT_TEST;
typedef struct _t_strust_test1
{
  unsigned char name:7;
  unsigned char bit:1;
}STRUCT_TEST1;
//根据协议栈的处理 可以适当的调整先name 再bit结构
int main()
{
  STRUCT_TEST *test = (STRUCT_TEST*)malloc(sizeof(STRUCT_TEST));
  printf("sizeof struct is %lu \n", sizeof(STRUCT_TEST));
  if(test == NULL)
  {
    printf("test is null \n");
    return -1;
  }
  //%02x  两位输出  不足2位 前面补0
  test->bit = 1;
  test->name = 0x1f; //31     合并001 1111 1  是?
  printf("struct is [%d], [%d] \n", test->bit, test->name); //0000 111 1
  printf(" bit:[%02x] char:[%c]\n",*(unsigned char *)test, *(char*)test);
  //这里只是demo,实际协议栈可以扩展
  //我的第一想法是内存直接拷贝/指针强转,可以实现赋值,除此之外,可以使用位运算
  //使用位运算,把char字符对应输入到结构体中。
  unsigned char c_test = *(char*)test;
  memset(test, 0, sizeof(STRUCT_TEST));
  printf("struct is NULL: [%d], [%d] \n", test->bit, test->name); //0000 111 1
  printf("get char [%02x]\n", c_test); //3f 0111 1111
  //& 如果对应位为1,则值为1,否则为0
  test->bit = c_test & 0x01;  //只取bit对应位的有效位  如果是在最高位  可以用0x80
  test->name = (c_test & 0xfe) >> 1;// & 1111 1110 取到name对应二进制位的所有的1,然后通过位移确定位置
    //>>右移符号
  printf("last get struct: bit:[%02x] char:[%c]\n",*(unsigned char *)test, *(char*)test);
  free(test);
  //如果倒换结构体位运算的定义,把一个char类型赋值给结构体的位运算
  unsigned char c_test1 = 0x91; //ASSII对应的是'字符  扩展的ASSII码,在Linux上测试时没有显示字符
  printf("char test1 is [%02x][%c] \n",c_test1, c_test1);
  STRUCT_TEST1 t_test1;
  t_test1.name = c_test1 & 0x7f;  //c_test1 & 7f = 1001 0001 & 0111 1111 = 1 0001
  t_test1.bit = (c_test1 & 0x80) >> 7; //1001 0001 & 1000 0000 = 1000 0000 右移7位
  printf("get test1 struct is [%02x] [%c] \n", *(unsigned char *)&t_test1, *(unsigned char *)&t_test1);
  return 0;
}
// 0x7f  0111 1111
目录
相关文章
|
3月前
|
存储 编译器 C语言
【C语言】结构体的大小是如何计算的?(结构体对齐)
【C语言】结构体的大小是如何计算的?(结构体对齐)
63 0
|
3月前
|
C语言
C语言5🔥:复合赋值,递增递减运算符,局部变量与全局变量
C语言5🔥:复合赋值,递增递减运算符,局部变量与全局变量
42 0
|
3月前
|
存储 C语言
C语言共用体成员输出的值与赋值时的不同的原因
在使用C语言的共用体时,如果成员输出的值与之前定义共用体变量的时候所赋值的不同,那么很可能是因为定义共用体变量的时候,为共用体的多个成员赋值造成的。因为共用体虽然允许在同一个内存位置上存储不同的数据类型的变量,但是任何时候都只能有一个成员存储值,也就是说,
67 2
|
存储 编译器 Linux
【C语言初阶】带你轻松玩转所有常用操作符最终篇——下标引用、函数调用和结构体成员,表达式求值
【C语言初阶】带你轻松玩转所有常用操作符最终篇——下标引用、函数调用和结构体成员,表达式求值
139 0
|
存储 C语言
C语言初识-关键字-操作符-指针-结构体
C语言初识-关键字-操作符-指针-结构体
54 0
|
存储 XML JSON
【C语言】结构体——我就是秩序的创建者!(结构体数组、结构体指针、嵌套、匿名、字面量、伸缩型数组、链式结构)
【C语言】结构体——我就是秩序的创建者!(结构体数组、结构体指针、嵌套、匿名、字面量、伸缩型数组、链式结构)
|
编译器 C++
自定义类型之结构体的基础和进阶(有关位段、结构体自引用、嵌套、内存对齐、修改对齐数、结构体的传参、和offsetof宏的使用)
一、结构体基础知识 二、结构体的进阶(有关结构体的自引用,嵌套,内存对齐和内存设计) (一、)首先是结构体的嵌套 (二、)结构体的自引用 (三、)结构体的内存对齐(如何计算结构体的所占内存大小) (四、)如何修改默认对齐数 三、offsetof的意思 四、结构体的传参 五、位段的使用和注意 总结:
|
C语言
【C语言】宏实现,计算结构体中某变量相对于首地址的偏移量
【C语言】宏实现,计算结构体中某变量相对于首地址的偏移量
155 0
【C语言】宏实现,计算结构体中某变量相对于首地址的偏移量
|
编译器 C语言
指针详细概念知识点及运用,指针与常量,指针的运算,scanf()中的&有什么用?你想知道的,都在这儿~ 1.1.4
f函数里的*p保存了i的地址,在这个函数指向i,此时对*p赋值,也就相当于对i值进行了改变,实现了对外链接,i的值变为了26,就是芥末神奇。此时以*q = 26为例,是可以做的,因为i不是const,i可以赋初值,使 i=26,但因为q是const,所以q++的做法是错误的。表示不能通过p这个指针去修改i这个变量,即*p=26是错误的,不能让 i=26,此时的*p是const。无论指向什么类型,所有指针的大小都是一样的,因为都是地址,但指向不同类型的指针是不能直接相互赋值的。......
指针详细概念知识点及运用,指针与常量,指针的运算,scanf()中的&有什么用?你想知道的,都在这儿~ 1.1.4
|
存储 C语言
C语言——结构体大小计数方法(结构体对齐)
C语言——结构体大小计数方法(结构体对齐)
120 0