1 结构体位域
1.1 位域
位域是一种节省空间的数据结构,是把一个数据类型按照二进制(二进位)划分为几个不同的区域,并说明每个区域的位数。
比如有一个字节,每一位表示一个开关状态,就可以使用位域,解析也方便。
unsigned char test7:1;
unsigned char test8:1;
这样收到1字节数据赋值给test,解析每个位的状态直接使用test.test1.....test.test6就可以,不需要再进行相应的位与操作之类的。还可以节省空间。要注意大小端,小端的test1是低位。
1.2位域的具体存储规则如下:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止。
2)如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始。
unsigned char test1:1;
unsigned char test2:4;
unsigned char test3:4;
unsigned char test4:1;
unsigned char test5:1;
unsigned char test6:1;
unsigned char test7:1;
unsigned char test8:1;
}
举例,这个test结构体,成员test3+test2+test1的位宽为9,大于char的8位,那从test3开始就要从第2个字节开始存。
编辑切换为居中
添加图片注释,不超过 140 字(可选)
3)如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,不建议使用,也没啥使用的必要。
4)如果位域字段之间穿插着非位域字段,则不进行压缩。
5)整个结构体的总大小为最宽基本类型成员大小的整数倍,和普通结构体一样。
2 __attribute__((packed))
__attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。
__attribute__关键字主要是用来在函数或数据声明中设置其属性。
3 联合使用
对于一些特殊的协议,比如sbus,sbus一个通道占11位,那按照位域的规则,下属代码中的channel3就要在存储在下一个unsigned int中了。就不满足我们直接利用编译器解析数据的目的了。
使用__attribute__ ((__packed__))处理,是可以使数据一个挨着一个,直接读取数据了。对于一些这种特殊协议的,这样联合使用比较方便。