嵌入式开发过程中结构体字节对齐问题pragma pack(1)

一、引言

曾经刚入门嵌入式在开发一个应用时,用到了自定义结构体,底层嵌入式单片机运行该结构体没问题,但是在Qt开发应用软件对接协议时,一直通不过,仔细分析才发现是QT这边的结构体字节并没有按照单字节对齐,后来在定义结构体时,增加了宏定义,强迫该结构体按照单字节对齐的方式进行编译,即可解决问题。

二、问题描述

假设有一个结构体,包含5字节头,一个字长度的负载,和一个字节的尾,例如:

typedef struct
{
    char head[5];
    unsigned short value;
    char endFlag;
}CMD_TypeDef;

CMD_TypeDef TCMD;

很明显,这个结构体的字节大小为5+2+1=8字节,但是用sizeof对各个域进行测试,发现总共的字节数并不是8,测试代码如下:

qDebug()<<"size"<<QString::number(sizeof(TCMD.head));  
qDebug()<<"size"<<QString::number(sizeof(TCMD.value));
qDebug()<<"size"<<QString::number(sizeof(TCMD.endFlag));
qDebug()<<"size"<<QString::number(sizeof(TCMD));

打印结果为:

size "5"
size "2"
size "1"
size "10"

进一步地,对这个结构体进行赋值,用并串口发出去该结构体的具体数据:

TCMD={{'A','T','+','D','='},10,0x0A};
port->write(( char*) &TCMD,sizeof(TCMD));

串口收到的数据为:41 54 2B 44 3D 1A 0A 00 0A 00

明显看到数据多了1A  和 00.

三、问题分析

从上面的串口收到结果来看,TCMD第一个成员head 变成了6字节【41 54 2B 44 3D 1A】,TCMD的成员endflag变成了2字节【0A 00】,结构体TCMD成员占用的内存分别是 6+2+2=10字节。

QT中定义的结构体在对成员进行内存分配时,往往按照“N”字节对齐的方式,即所有内容按照N字节的方式进行占用内存,如果剩余的内容占不满N字节,则N字节剩下的字节仍然给该结构成员,新的成员重新从下一个N字节进行对齐。

以上面的例子来说,显然N=2,即机构体按照2字节进行对齐,TCMD的头部head占5字节,需要占用3个N=6字节,负载value等于2字节,刚好占用一个N,而尾部endflag占用1字节,不足N,仍然需要占用一个N。

四、解决方法

既然QT编译系统对结构体按照N字节对齐,那么能否根据需要指定对齐的N数呢,其实C语言提供了这种操作,采用宏定义:

#pragram pack(N)
......//结构体定义内容
#pragram pack()

即可指定该定义的结构体内存对齐方式。

具体地,上述问题可以这样解决:

#pragram pack(1)
typedef struct
{
    char head[5];
    unsigned short value;
    char endFlag;
}CMD_TypeDef;
#pragram pack()

CMD_TypeDef TCMD;
 

结构体定义的时候加上:#pragma pack(1)

定义结束部分结尾 #pragma pack()即可。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值