数据字节对齐案例

1、发现问题

项目需要使用上位机配置,所以列了一个结构体包含了浮点数和整形和短整型,可以查看下面的数据,

union
 {
  struct
  {
   float AD[AD_NUM];//当前AD工程量 32 0 R
   u8 DX[DI_NUM];//当前输入 4  32 R
   u8 DY[DO_NUM];//当前输出 2 36  RW

   u8 AD_EN[AD_NUM]; //使用工程量 8 38 不适用默认0-32000 RW
   float AD_LLim[AD_NUM]; //AD工程量下限 32 46 RW 
   float AD_HLim[AD_NUM]; //AD工程量上限 32 78 RW
   u16 ADSampNum[AD_NUM]; //AD采样数 16 110 RW

   float DISampNum[DI_NUM]; //DI滤波时间 单位 ms 16 126 RW
   u8 DO_StopOut[DO_NUM];//停机输出 2 142 RW
   u8 CorreEN[AD_NUM];//修正启用  默认不启用防止误操作 8 144 RW
   float ZeroCorre[AD_NUM];//AD零点修正值 32 152 RW
   float CoefCorre[AD_NUM];//AD系数修正值 32 184 RW
   u8 ZZZZZ[10];//预留 10 216 RW
   u8 AllCorreEN;//一键零点修正 1 226 RW
   u8 AllDefault;//恢复默认值 1 227 RW
   u8 NAddr;//从站地址 1 228    RW
   union
   {
    struct
    {
     u8 len:1;//数据长度[0] :0- 8位;1-7位
     u8 cek:2;//奇偶校验[1:2] :00-无校验; 01-奇校验O; 11-偶校验E
     u8 stop:1;//停止位[3]:0-1位;1-2位 
     u8 bood:4;//波特率[4-7]:0-9600; 1-19200;2-38400;3-57600; 4-115200
    }stu;
    u8 Da;// 1 229通讯配置:    RW
   }COMx;
   char ModeName[10];//10 230 名字 R
   char ModeVnum[10];//10 240 版本 R
  }stuTD;
  u8 Arr[BM_LEN];
 }uniCFG;

正常来说数据正常我的240开始应该是我定义的版本数据:v1.0  :

实际却是这样子,偏移了4位,

2、查找问题

既然位置不对,全部赋值检查位置数据哪里开始错误;

一步步找发现在地址 46和47这边却没有数据,我明明已经全部赋值了,毛病就在这里!但是是什么原因导致的呢?

检查数据类型和长度

在单字节类型的后面出错,后面是浮点型4字节,照理来说没错啊;一万个马崩腾而过。。。又来bug了吗。。。

3.解决问题

突然想到是两个有问题,上面的单字节的长度加起来只有 14 ,加上2就是16,16才能字节对齐。下面还有一个也是只有2字节的没对齐,补齐的话加起来刚好4个,也就是偏移的4个数据;

感觉有戏,把下面的2个字节的提上来,修改后的结构体

union
    {
        struct
        {
            float AD[AD_NUM];//当前AD工程量 32 0-31 R
            u8 DX[DI_NUM];//当前输入 4  32-35 R
            u8 DY[DO_NUM];//当前输出 2 36-37  RW
            u8 DO_StopOut[DO_NUM];//停机输出 2 38-39 RW
            u8 AD_EN[AD_NUM]; //使用工程量 8 40-47 不适用默认0-32000 RW
            float AD_LLim[AD_NUM]; //AD工程量下限 32 48-79 RW 
            float AD_HLim[AD_NUM]; //AD工程量上限 32 80-111 RW
            u16 ADSampNum[AD_NUM]; //AD采样数 16 112-127 RW

            float DISampNum[DI_NUM]; //DI滤波时间 单位 ms 16 128-143 RW
            u8 CorreEN[AD_NUM];//修正启用  默认不启用防止误操作 8 144-151 RW
            float ZeroCorre[AD_NUM];//AD零点修正值 32 152-183 RW
            float CoefCorre[AD_NUM];//AD系数修正值 32 184-215 RW
            u8 ZZZZZ[10];//预留 10 216-225 RW
            u8 AllCorreEN;//一键零点修正 1 226 RW
            u8 AllDefault;//恢复默认值 1 227 RW
            u8 NAddr;//从站地址 1 228    RW
            union
            {
                struct
                {
                    u8 len:1;//数据长度[0] :0- 8位;1-7位
                    u8 cek:2;//奇偶校验[1:2] :00-无校验; 01-奇校验O; 11-偶校验E
                    u8 stop:1;//停止位[3]:0-1位;1-2位 
                    u8 bood:4;//波特率[4-7]:0-9600; 1-19200;2-38400;3-57600; 4-115200
                }stu;
                u8 Da;// 1 229通讯配置:       RW
            }COMx;
            char ModeName[10];//10 230-239 名字 R
            char ModeVnum[10];//10 240-249 版本 R
        }stuTD;
        u8 Arr[BM_LEN];
    }uniCFG;

重新编译,见证奇迹!!

完美解决

后话:其实原来都是理论上说道什么字节对齐什么的,实际中遇到的没有,有时可能这辈子都根本不会遇到,遇到这实际的问题拿出来分享一下,给大家点实际体会,希望对大家有帮助!!

 

原文地址:https://www.cnblogs.com/luckytimor/p/11212485.html