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

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

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

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

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

收获到的基础知识点:

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

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

​ >>和<< :由于结构体位域自定义了目标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
根据提供的引用内容,Python解析位域结构体需要考虑大端格式和小端格式。对于大端格式,不需要进行其他转换操作,只需对起始位及长度进行判断即可自动生成自动化代码。而对于小端格式,需要进行字节序转换后再进行解析。 以下是Python解析位域结构体的示例代码: ```python import struct # 定义位域结构体 class BitFieldStruct: def __init__(self, data): self.field1 = (data[0] >> 7) & 0x01 self.field2 = (data[0] >> 6) & 0x01 self.field3 = (data[0] >> 5) & 0x01 self.field4 = (data[0] >> 4) & 0x01 self.field5 = (data[0] >> 3) & 0x01 self.field6 = (data[0] >> 2) & 0x01 self.field7 = (data[0] >> 1) & 0x01 self.field8 = data[0] & 0x01 self.field9 = (data[1] >> 7) & 0x01 self.field10 = (data[1] >> 6) & 0x01 self.field11 = (data[1] >> 5) & 0x01 self.field12 = (data[1] >> 4) & 0x01 self.field13 = (data[1] >> 3) & 0x01 self.field14 = (data[1] >> 2) & 0x01 self.field15 = (data[1] >> 1) & 0x01 self.field16 = data[1] & 0x01 # 定义数据 data = b'\x12\x34' # 解析大端格式的位域结构体 bit_field_struct = BitFieldStruct(data) print(bit_field_struct.field1) print(bit_field_struct.field2) print(bit_field_struct.field3) print(bit_field_struct.field4) print(bit_field_struct.field5) print(bit_field_struct.field6) print(bit_field_struct.field7) print(bit_field_struct.field8) print(bit_field_struct.field9) print(bit_field_struct.field10) print(bit_field_struct.field11) print(bit_field_struct.field12) print(bit_field_struct.field13) print(bit_field_struct.field14) print(bit_field_struct.field15) print(bit_field_struct.field16) # 解析小端格式的位域结构体 little_endian_data = struct.unpack('<H', data)[0] little_endian_bit_field_struct = BitFieldStruct(struct.pack('>H', little_endian_data)) print(little_endian_bit_field_struct.field1) print(little_endian_bit_field_struct.field2) print(little_endian_bit_field_struct.field3) print(little_endian_bit_field_struct.field4) print(little_endian_bit_field_struct.field5) print(little_endian_bit_field_struct.field6) print(little_endian_bit_field_struct.field7) print(little_endian_bit_field_struct.field8) print(little_endian_bit_field_struct.field9) print(little_endian_bit_field_struct.field10) print(little_endian_bit_field_struct.field11) print(little_endian_bit_field_struct.field12) print(little_endian_bit_field_struct.field13) print(little_endian_bit_field_struct.field14) print(little_endian_bit_field_struct.field15) print(little_endian_bit_field_struct.field16) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值