1.问题点环境
STM32 开发项目使用结构体
2.嵌套结构体
typedef struct{
u32 valid_time1;
u32 valid_time2;
u32 valid_time3;
}time_types;
typedef struct{
u8 time_zone_id;
time_types monday_time;
time_types tuesday_time;
time_types wednesday_time;
time_types thursday_time;
time_types friday_time;
time_types saturday_time;
time_types sunday_time;
time_types holiday_time1;
time_types holiday_time2;
time_types holiday_time3;
}time_zone_group;
time_zone_group time_zone_group_buf;
定义结构体变量time_zone_group_buf 后使用该变量串口接收上位机数据时,发现单片机分配的内存地址将结构体中time_zone_id 给了4个字节也就是跟后面u32类型同一个字节数,如下图debug时的地址:
time_zone_group 的地址是0x20007CAC,我设定的变量time_zone_id类型是u8类型,也就是一个字节,但monday_time的地址是0x20007CB0,&time_zone_group 和 &monday_time相差有4个字节?后面变量的内存分配字节数都是正常的
原因分析:
查看资料结构体初始化时,所占的空间将按照占用最大的成员类型所占字节数的整数倍,对于其他成员编译器将自动补齐对应的字节数,也就是说,因为我其他成员变量都是4个字节,而只有time_zone_id 成员是1个字节,编译器在编译的时候自动补全了3个字节。
注: 关于结构体对齐问题,跟单片机系统有关,结合四种对齐规律进行理解:指定对齐值、自身对齐值、有效对齐值、成员偏移量。
在编译时指定该结构体不要自动对齐。
第一种方式:#pragam pack(n) n表示对齐的字节数
#pragam pack(1)
struct C
{
char a;
int b;
short c;
};#pragam pack() //还原默认对齐
如不加上#pragam pack() 后面的结构体将都按照1字节当时对齐
第二种方式:attribute((packet))
struct C
{
char a;
int b;
short c;
}__attribute__((packet));
总结:
字节对齐弊端,在跨平台时可能会造成空间消费更大,且有可能导致数据错乱;
可以人为的占位处理
struct C
{
char a;
char reserve[3];
int b;
short c;
char reserve[2];
}
使用结构体建议:
1.结构体成员合理安排位置,以节省空间;
2.跨平台数据结构可以考虑1字节对齐方式,节省了空间,但影响访问效率;
3.跨平台数据结构人为进行字节填充,提高访问效率但不节省空间;
4.本地数据才用默认对齐方式,以提高访问效率。