C#关于使用Marshal.StructureToPtr保存文件

在C#中使用以下两个方法进行序列化和反序列化中,如果结构体AnyStruct内容采用[StructLayout(LayoutKind.Sequential)]则会造成在结构体中添加成员变量后由于内存没有对齐,使得原来的变量值受到影响。

private byte[] Serialize(object obj)

        {
            int rawSize = Marshal.SizeOf(obj);
            IntPtr buffer = Marshal.AllocHGlobal(rawSize);
            Marshal.StructureToPtr(obj, buffer, false);
            byte[] rawDatas = new byte[rawSize];
            Marshal.Copy(buffer, rawDatas, 0, rawSize);
            Marshal.FreeHGlobal(buffer);
            return rawDatas;
        }

 private AnyStruct Deserialize(byte[] rawDatas)

        {
            Type anyType = typeof(AnyStruct);
            int rawSize = Marshal.SizeOf(anyType);
            if (rawSize > rawDatas.Length) return new AnyStruct();
            IntPtr buffer = Marshal.AllocHGlobal(rawSize);
            Marshal.Copy(rawDatas, 0, buffer, rawSize);
            object retobj = Marshal.PtrToStructure(buffer, anyType);
            Marshal.FreeHGlobal(buffer);
            return (AnyStruct)retobj;

        }


如下所示,当采用[StructLayout(LayoutKind.Explicit)]标记每个成员变量在内存中的存放位置时则在Y3后添加字节数等于或者小于float的变量后不会影响原来的值,但当添加一个double类型的参数后还是会影响原来的成员变量的值。

        [StructLayout(LayoutKind.Explicit)]
        public struct AnyStruct
        {
            [FieldOffset(0)]
            public int ID;
            [FieldOffset(8)]
            public ushort Type;
            [FieldOffset(16)]
            public float X1;
            [FieldOffset(24)]
            public float Y1;
            [FieldOffset(32)]
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
            public byte[] data;
        }

当把以上结构体中的任意一个成员变量改为double类型,则后续随意加什么类型的变量都不会对之前的成员变量造成影响。

总结:是否采用[StructLayout(LayoutKind.Explicit)]后结构体中如果最大为float,也就是4byte,虽然规定之前的每个成员变量的位置为相隔8byte,但是剩余的128byte还是安装最大成员变量float的4byte进行排列,导致添加一个double的8byte变量时内存对齐错误,而当之前的成员变量里含有一个double的8byte时,后续的128byte都是按照相隔8byte来排列,也就不会出错,望高手解答!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值