在做通信协议处理的时候,接收到对端的数据,需要根据固定的结构去做解析。
在某些场景下,需要把字符按一定协议赋值给自己定义的结构体(涉及位域)
我的第一想法是直接强转指针或者按位拷贝,但不能适应所有场景。
可以通过位运算 使用位运算符& 和>> 实现数据的获取.
收获到的基础知识点:
把一个字符赋值给有位域相关的内存时,可以采用位运算符& 和 >> ,<<实现:
&: 提取到一个字节中,对应位置的对应值
>>和<< :由于结构体位域自定义了目标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