更多课程 选择中心

C/C++培训
达内IT学院

400-996-5531

C语言结构体对齐的陷阱

  • 发布:C++培训
  • 来源:学习笔记
  • 时间:2017-09-29 16:27

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

以下面一段代码为例:

#include <stdio.h>

#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)计算偏移量,二者的效果是相同的。

预约申请免费试听课

填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:C语言char字符串与中文编码的坑
下一篇:设计模式(C++) - 单例模式

C语言创建windows窗口实例

C++回调函数是什么?

C++ shared_ptr和动态数组

C语言有哪些关键词,C语言44个关键词大全

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省