c语言编译结构体padding,C语言结构体对齐的陷阱

在通信协议的开发过程中,有时会利用结构体构造报文某些字段,这就有可能会涉及到结构体对齐的问题。如果稍有不慎,会因结构体使用不当导致功能受到严重影响。

以下面一段代码为例:

#include

#define PKT_TIMESTAMP_LEN 8

typedef struct pktIdentifyTlv_s

{

unsigned char type;              /*type = 0xfe*/

unsigned char len[2];            /*len = 0x09*/

unsigned char reserved;          /*四字节对齐*/

unsigned char operID[4];

unsigned char identify[2];       /*报文标识*/

unsigned char highTransID[2];    /*四字节对齐*/

} pktIdentifyTlv_t;

typedef struct pktTimeStampData_s

{

unsigned char timeStamp1[PKT_TIMESTAMP_LEN];     /*T1*/

unsigned char timeStamp2[PKT_TIMESTAMP_LEN];     /*T2*/

unsigned char timeStamp3[PKT_TIMESTAMP_LEN];     /*T3*/

unsigned char timeStamp4[PKT_TIMESTAMP_LEN];     /*T4*/

}pktTimeStampData_t;

typedef struct cfmCommonHeader_s

{

unsigned char mdLevel_ver;       /*MD等级-前3位(0-7),MD版本-0*/

unsigned char opcode;            /*详见Y.1731协议*/

unsigned char flags;             /*标记(0)*/

unsigned char firstTLVoffset;    /*第一个TLV的偏移(4)*/

} cfmCommonHeader_t;

typedef struct dmmPdu_s

{

cfmCommonHeader_t stCfmComHeader; /*CFM COMMON头*/

pktTimeStampData_t stTimeStampData;  /*时间戳信息*/

pktIdentifyTlv_t stIdentifyTlv;

unsigned char endTlv;

}dmmPdu_t;

typedef struct counterData_s

{

long TxFCf;  /*远端发送帧计算*/

long RxFCf;  /*远端接收帧计算*/

long TxFCb;  /*LMR帧传输时本地计数器TxFCl的数值*/

}counterData_t;

typedef struct lmmPdu_s

{

cfmCommonHeader_t stCfmComHeader; /*CFM COMMON头*/

counterData_t stCounterData;      /*计数器信息*/

pktIdentifyTlv_t stIdentifyTlv;

unsigned char endTlv;

}lmmPdu_t;

int main()

{

int lmm = sizeof(lmmPdu_t);

int dmm = sizeof(dmmPdu_t);

int com_head = sizeof(cfmCommonHeader_t);

int lmm_cnt = sizeof(counterData_t);

int dmm_cnt = sizeof(pktTimeStampData_t);

int id_tlv = sizeof(pktIdentifyTlv_t);

printf("\r\nlmm=%d, dmm=%d\r\n", lmm, dmm);

printf("\r\ncom_head=%d, id_tlv=%d\r\n", com_head, id_tlv);

printf("\r\nlmm_cnt=%d, dmm_cnt=%d\r\n", lmm_cnt, dmm_cnt);

return 0;

}

上述例程在windows XP上C Free 5.0中的运行结果为:

从结果中可以看到,结构体lmmPdu_t按照成员的最大宽度long型进行对齐(按照4字节对齐,编译器对结构体进行了padding),而dmmPdu_t由于成员都是char型(按照1字节对齐,编译器没有对结构体进行padding)。

如果想对lmm报文的stIdentifyTlv字段进行改写,应该从lmmPdu的头部向后偏移24。通过(lmm - 5)计算偏移量,对stIdentifyTlv字段的填充是错误的。

而对于改写dmm报文的stIdentifyTlv字段,可以从dmmPdu的头部向后偏移44,亦可以通过(dmm - 5)计算偏移量,二者的效果是相同的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值