KEIL中结构体对齐笔记
在协议的解析和组包过程中,使用结构体是比较的方便的。但是一般在32位系统一般是4字节对齐,如果能指定结构体对齐数则可以解决在数据解析中数据位错乱的问题。
1.未使用结构体对齐操作
(1)首先定义一个结构体。
struct TestStruct2
{
unsigned char head1;
unsigned short
bit1: 4,
bit2: 4,
bit3: 8;
unsigned int add;
unsigned char end1;
unsigned char end2;
};
(2)解析数据帧操作
unsigned char buf[14] = {0xaa,0x5A,0xAA,0x12,0x34,0x56,0x78,0xE1,0xE2};
struct TestStruct2 *p = (struct TestStruct2 *)(buf);
printf(" sizeof = %d \r\n",sizeof(struct TestStruct2) );
printf(" %02X %02X %02X %02X %08X %02X ",p->head1, p->bit1, p->bit2, p->bit3,p->add, p->end1 ,p->end2);
(3)输出结果
sizeof = 12
head = AA bit = 0A 05 AA add = E1785634 end E2 00
结构体struct TestStruct2占有12个字节,解析的结构并未达到预期结果。
2.指定结构体对齐操作
(1)定义一个结构体。
#pragma pack (1) // 指定结构体按照1字节对齐
struct TestStruct1
{
unsigned char head1;
unsigned short
bit1: 4,
bit2: 4,
bit3: 8;
unsigned int add;
unsigned char end1;
unsigned char end2;
};
#pragma pack () // 取消结构体对齐
(2)解析数据帧操作
unsigned char buf[14] = {0xaa,0x5A,0xAA,0x12,0x34,0x56,0x78,0xE1,0xE2};
struct TestStruct1 *p = (struct TestStruct2 *)(buf);
printf("\r\n sizeof = %d \r\n",sizeof(struct TestStruct1) );
printf(" head = %02X bit = %02X %02X %02X add = %08X end %02X %02X",p->head1, p->bit1, p->bit2, p->bit3,p->add, p->end1 ,p->end2);
(3)输出结果
sizeof = 9
head = AA bit = 0A 05 AA add = 78563412 end E1 E2
结构体*struct TestStruct1占有9个字节,成功的解析出了head 和 end 字段。其他字段由于MCU一般默认是小端模式导致。
备注:
数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,每个数据成员存储的起始位置要从该成员(每个成员本身)大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.
结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍(结构体成员以最大成员为代表).不足的要补齐.