union中结构体整合后字节对齐问题

续上篇博文:http://www.cnblogs.com/flamefox/p/4241176.html

上次把结构体的编译问题解决了,这次又来了新问题,客户端和服务器访问相同的结构,出现了bug

原始的代码如下(结构1):

struct MsgInfo
{
    union
    {
      struct   //for exp
      {
        OBJID idType;
        USHORT usLevel;
        UINT  unExp;
      };
      struct  //for learn
      {
        OBJID idType;
        USHORT usLevel;
        UCHAR ucResult;
      };

      struct  //for update
      {
        OBJID  idType;
        USHORT usLevel;
        UCHAR  ucResult;
      };

    }
}

可以看到这3个结构的前2个字段都是一样,于是后续开发的程序员为了省事,做了一下变化,

改成下面这样(结构2):

 struct  //for learn
      {
        OBJID idType;
        USHORT usLevel;
        union
        {
           UINT  unExp;
           UCHAR ucResult;
        };
      };

可以看到,一个struct就解决问题了,但是问题来了,服务器和客户端的数据不匹配了

检查代码后,我们一致认定是对齐问题造成的问题,由于代码是8字节对齐的,分析如下:

从之前旧的结构改为新的结构后,看似没有什么不同,但是如果考虑对齐的话,就会有很大的问题

结构2的对齐

idType 4
usLevel 2 补全到4
ucResult 1 和
unExp 4 共用一块内存

结构1的对齐

struct  //for learn
      {
        OBJID idType; 4
        USHORT usLevel; 2
        UCHAR ucResult; 1
      };

其只有7字节,补齐到8字节,这意味着

客户端和服务端读取和写入数据的字节的位置完全不一样,之前那位修改结构的同学修改出错了。而客户端由于其他的原因可以“正常”的显示,问题在当时没有暴露。

所以最后还是要修改回原始的方式。。切记不要过早优化啊

时间: 2024-08-28 11:54:11

union中结构体整合后字节对齐问题的相关文章

黑马程序员--C语言中结构体-我之理解

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 什么是结构体? “结构”是一种构造类型,它是由若干“成员”组成的.每一个成员可以是一个基本数据类型或者又是一个构造类型. 为什么要有结构类型? 结构体可以把功能相同的数据组织起来,存在一起,用的时候方便,而且在调用函数时,若 传递参数较多

C语言中结构体内部成员的对齐

说明: ******不同的编译器和处理器,其结构体内部的成员有不同的对齐方式. ******使用sizeof()运算符计算结构体的长度. ###结构体中每个成员相对于结构首地址的偏移量都是成员大小的整数倍,如果有需要编译器会在成员之间加上填充字. ###结构体的总大小是结构体最宽基本类型成员大小的整数倍.如果需要编译器会在最后一个成员之后加上填充字. struct A { <span style="white-space:pre"> </span>unsigne

OpenCV 中结构体IplImage 成员width widthStep使用注意事项

OpenCV 中结构体IplImage 成员width,widthStep使用注意事项 width 是指的图片宽度是多少个像素,而这里widthStep是指的图片中的每一行占用多少个字节. 而且,widthStep会有字节对齐. 当需要对每个像素进行操作的时候,这里最好用widthStep做行递增变换. 比方说这里就是一个例子,明显,ptr_pixel_tmp是指向double类型的三通道图像,而ptr_pixel_img是unsigned char类型的三通道图像,double占八个字节. 于

OC类中一些细节问题(对象类存储、类中结构体的用法)

一:OC中得方法名 注意:方法名冒号和后面的and方法名冒号  都是方法名 一:对象的存储细节 类加载到代码区(包括类中得属性和方法).对象动态加载到堆内存中.指向对象的指针存放在栈区. 三:定义类常见的错误 定义类的时候,常见的错误 1)类的定义不能嵌套 2)不要漏写 @end 3) 不要忘记写实现类(如果忘记写了,编译不会报错,运行时候才报错) 4)定义成员变量的大括号经常漏写 5) 如果不写@interface 只有 @implementation 这可以,但是会报警告,建议不要这么写 6

C#中结构体与字节流互相转换

1.定义与C++对应的C#结构体 在c#中的结构体不能定义指针,不能定义字符数组,只能在里面定义字符数组的引用. C++的消息结构体如下: //消息格式 4+16+4+4= 28个字节 struct cs_message{ u32_t cmd_type; char username[16]; u32_t dstID; u32_t srcID; }; C#定义的结构体如下: [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct

C语言中结构体赋值问题的讨论(转载)

今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言中结构体赋值的问题吧: 结构体直接赋值的实现 下面是一个实例: #include <stdio.h> struct Foo { char a; int b; double c; }foo1, foo2; //define two structs with three different field

C++中结构体和类的区别

在C++中,结构体是一种特殊形态的类. 结构体和类的唯一区别就是:  结构体和类具有不同的默认访问控制属性. 类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型(private) 结构体中,对于未指定任何访问控制属性的成员,其访问控制属性为公有类型(public) C++中,不使用结构体丝毫不会影响程序的表达能力.C++之所以要引入结构体,是为了保持和C程序的兼容性. 但有时仍会在C++中使用结构体,是因为,可以使用结构体将不同类型数据组成整体,方便于保存数据.(若用类来保存,因类中成

C /C ++中结构体的定义

c语言中结构体的定义: struct 结构体名{ 成员列表: ..... }结构体变量: 7.1.1 结构体类型变量的定义结构体类型变量的定义与其它类型的变量的定义是一样的,但由于结构体类型需要针对问题事先自行定义,所以结构体类型变量的定义形式就增加了灵活性,共计有三种形式,分别介绍如下:1) 先定义结构体类型,再定义结构体类型变量:struct stu / *定义学生结构体类型* /{char name[20]; / * 学生姓名* /char sex; / * 性别* /long num;

修改Dictionary或List中结构体struct值的问题

问题:修改Dictionary中结构体struct值的值,如果直接用Dictionary[key].a += XX;(a为结构体中某数值型属性) ,则会报错: 无法修改.Dictionary<int,struct>.this[int]”的返回值,因为它不是变量 如果用一个变量承接Dictionary[key]中的结构体,即struct newStr =Dictionary[key],然后再做出修改:newStr.a += XX,则Dictionary中对应的结构体的值不发生变化.(由此可判断结