将结构体转为字节流的方式
分类:计算机编程

1、 将基础项目转为byte数组存款和储蓄

 1  private byte[] CreateNetDataByteStream(ushort system, ushort host, ushort type, byte[] tx_buf, ushort msg_len, ushort flag)
 2 
 3         {
 4 
 5             if (tx_buf == null)
 6 
 7             {
 8 
 9                 return null;
10 
11             }
12 
13             try
14 
15             {
16 
17                 byte[] data = new byte[msg_len   NetDataHeadLen];
18 
19                 byte[] u16byte = new byte[2];
20 
21                 u16byte = BitConverter.GetBytes(type);
22 
23                 Array.Copy(u16byte, 0, data, 0, 2);
24 
25                 u16byte = BitConverter.GetBytes(flag);
26 
27                 Array.Copy(u16byte, 0, data, 4, 2);
28 
29                 u16byte = BitConverter.GetBytes(msg_len);
30 
31                 Array.Copy(u16byte, 0, data, 2, 2);
32 
33                // u16byte = BitConverter.GetBytes(CommonConstant.MySystemID);
34 
35                 Array.Copy(u16byte, 0, data, 6, 2);
36 
37               //  u16byte = BitConverter.GetBytes((ushort)CommonConstant.MySeatName);
38 
39                 Array.Copy(u16byte, 0, data, 8, 2);
40 
41                 u16byte = BitConverter.GetBytes(system);
42 
43                 Array.Copy(u16byte, 0, data, 15, 2);
44 
45                 u16byte = BitConverter.GetBytes(host);
46 
47                 Array.Copy(u16byte, 0, data, 17, 2);
48 
49                 tx_buf.CopyTo(data, NetDataHeadLen);
50 
51                 return data;
52 
53             }
54 
55             catch
56 
57             {
58                 return null;
59 
60             }
61 
62         }

2.C#中协会体 与 字节流 互相转变

       

方式一
        //将一个结构序列化为字节数组
               private IFormatter formatter = new BinaryFormatter();
        private ValueType deserializeByteArrayToInfoObj(byte[] bytes)
        {
            ValueType vt;
            if (bytes == null || bytes.Length == 0)
            {
                return null;
            }

            try
            {
                MemoryStream stream = new MemoryStream(bytes);
                stream.Position = 0;
                stream.Seek(0, SeekOrigin.Begin);
                vt = (ValueType)formatter.Deserialize(stream);
                stream.Close();
                return vt;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        //将一个结构序列化为字节数组
        private byte[] serializeInfoObjToByteArray(ValueType infoStruct)
        {
            if (infoStruct == null)
            {
                return null;
            }

            try
            {
                MemoryStream stream = new MemoryStream();
                formatter.Serialize(stream, infoStruct);

                byte[] bytes = new byte[(int)stream.Length];
                stream.Position = 0;
                int count = stream.Read(bytes, 0, (int)stream.Length);
                stream.Close();
                return bytes;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

方式二
   /// <summary>
        /// 将字节数组转换为结构体
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public object ByteaToStruct(byte[] bytes, Type type)
        {
            //得到结构体大小
            int size = Marshal.SizeOf(type);
            Math.Log(size, 1);

            if (size > bytes.Length)
                return null;
            //分配结构大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将BYTE数组拷贝到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内容空间
            Marshal.FreeHGlobal(structPtr);
            return obj;
        }
        /// <summary>
        /// 将结构转换为字节数组
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public byte[] StructTOBytes(object obj)
        {
            int size = Marshal.SizeOf(obj);
            //创建byte数组
            byte[] bytes = new byte[size];
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷贝到分配好的内存空间
            Marshal.StructureToPtr(obj, structPtr, false);
            //从内存空间拷贝到byte数组
            Marshal.Copy(structPtr, bytes,0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }

3. C# 结构体字节对齐

1 [structLayout(Layoutkind.sequential,charset=charset.ansi)]
2 Struct Mystruct
3 {
4 [MarshalAs(UnmanagedType.ByValArray,sizeConst=8)]
5 Public byte[] serial;
6 Public byte Type;
7 Public uint Sum;
8 }

在上述结构体与字节流转换第三种艺术中,获取结构体长度int size = 马尔斯hal.SizeOf(Mystruct);,并非13,而是16。在内部存款和储蓄器特定项目数据结构早先地址日常有自然的对齐需求,比如叁十个人机器的int起先地址必得是4的大背头倍,结构平日也这么

亟需加上[structLayout(Layoutkind.sequential,charset=charset.ansi,pack=1)]

转自:

1. 结构体(struct)

1.1 结构体的概念

  • 结构体(struct):是由风流倜傥多级具备相仿种类或不一致品类的数码整合的数码集结,叫做结构。
  • 结构体(struct):是后生可畏种复合数据类型,结构类型。
  • 注:“结构”是生龙活虎种构造类型,它是由若干“成员”组成的。 每二个分子可以是六个中央数据类型只怕又是一个构造类型。 结构正是黄金时代种“构造”而成的数据类型, 那么在验证和平运动用早前必需先定义它,也正是构造它。就如在印证和调用函数早先要先定义同样。

1.2 C语言中的结构体

  • 说明:在C语言中,结构体(struct)是复合数据类型的风流浪漫种。同期也可以有个别要素的集合,那些要素称为结构体的积极分子,且这几个成员可以为差别的品种,成员日常用名字访谈。结构体能够被声称为变量、指针或数组等,用以落成较复杂的数据结构。
  • 注:在C语言中,结构体不能满含函数。
  • 概念与注解: (1)示例代码生机勃勃:

    1 struct tag 
    2 {
    3     member-list
    4 }variable-list;
    5 注:struct为结构体关键字;
    6    tag为结构体的标志;
    7    member-list为结构体成员变量列表,其必须列出其所有成员;
    8    variable-list为此结构体声明的变量;
    

    (2)示例代码二:

     1 //此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c,但没有标明其标签,声明了结构体变量s1
     2 struct 
     3 {
     4     int a;
     5     char b;
     6     double c;
     7 } s1;
     8 
     9 //此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c,结构体的标签被命名为SIMPLE,用SIMPLE标签的结构体,另外声明了变量t1, t2[20], *t3
    10 struct SIMPLE
    11 {
    12     int a;
    13     char b;
    14     double c;
    15 };
    16 SIMPLE t1, t2[20], *t3; 
    17 
    18 //可以用typedef创建新类型,此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c,结构体的标签被命名为Simple2,用Simple2作为类型声明新的结构体变量u1, u2[20], *u3
    19 typedef struct
    20 {
    21     int a;
    22     char b;
    23     double c; 
    24 } Simple2;
    25 Simple2 u1, u2[20], *u3;//若去掉typedef则编译报错,error C2371: “Simple2”: 重定义;不同的基类型
    26 
    27 注:在上面的声明中,第一个和第二声明被编译器当作两个完全不同的类型,即使他们的成员列表是一样的,如果令t3=&s1,则是非法的。
    

    注:在形似意况下,tag、member-list、variable-list那3片段起码要出新2个。

1.3 C 中的结构体

  • 说明:在C语言中,结构体无法富含函数。在面向对象的主次设计中,对象具备状态(属性)和行为,状态保存在成员变量中,行为经过分子方法(函数)来兑现。C语言中的结构体只可以描述一个对象的情景,不能够描述二个指标的表现。在C 中,思索到C语言到C 语言过渡的三回九转性,对结构体举办了扩展,C 的结构体能够包罗函数,那样,C 的结构体也具有类的成效,与class分歧的是,结构体包涵的函数默感到public,并非private。
  • 注:在C 中,结构体能够包涵函数。
  • 概念与证明:

  • (1)示例代码后生可畏:

    1 struct tag 
    2 {
    3     member-list
    4 }variable-list;
    5 注:struct为结构体关键字;
    6    tag为结构体的标志;
    7    member-list为结构体成员变量及成员函数列表,其必须列出其所有成员;
    8    variable-list为此结构体声明的变量;
    

    (2)示例代码二:

     1 #include <iostream> 
     2 
     3 using namespace std;
     4 
     5 struct SAMPLE
     6 {
     7     int x;
     8     int y;
     9     int add() {return x y;}
    10 }s1;
    11 
    12 int main()
    13 {
    14     cout<<"没初始化成员变量的情况下:"<<s1.add()<<endl;
    15     s1.x = 3;
    16     s1.y = 4;
    17     cout<<"初始化成员变量的情况下:"<<s1.add()<<endl;
    18     system("pause");
    19     return 0;
    20 }
    21 =>没初始化成员变量的情况下:0
    22   初始化成员变量的情况下:7
    

    C 中的结构体与类的不相同: (1)class中私下认可的成员访谈权限是private的,而struct中则是public的。 (2)class承继暗许是private继承,而从struct承接默许是public承继。

1.4 结构体的成效

  • 在骨子里项目中,结构体是大方设有的。研究开发人士常使用结构体来封装一些性质来组合新的品种。由于C语言内部程序比较简单,研发职员常常接纳结构体创制新的“属性”,其指标是简化运算。
  • 结构体在函数中的成效不是便捷,最重要的效力便是包装。打包的平价正是可以再度使用。让使用者不必关注那些是怎么,只要依照定义使用就能够了。

1.5 结构体的尺寸与内部存款和储蓄器对齐

  • 暗中认可的对齐格局:各成员变量在寄放的时候依据在构造中冒出的顺序依次申请空间,同期依据地方的对齐情势调节位置,空缺的字节VC会自动填写。同期VC为了保险组织的高低为布局的字节边界数(即该组织中据有最大空间的体系所据有的字节数)的翻番,所以在为尾声八个分子变量申请空间后,还有恐怕会基于供给活动填充空缺的字节。

  • 注:VC对变量存储的一个特种管理。为了巩固CPU的存款和储蓄速度,VC对有的变量的最初地址做了“对齐”管理。在默许意况下,VC规定各成员变量寄存的初步地址相对于组织的初始地址的偏移量必需为该变量的项目所据有的字节数的翻番。

  • (1)示例代码风流倜傥:

    1 struct MyStruct
    2 {
    3     double dda1;
    4     char dda;
    5     int type;
    6 };
    7 //错:sizeof(MyStruct)=sizeof(double) sizeof(char) sizeof(int)=13。
    8 //对:当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。
    

    注:为地点的布局分配空间的时候,VC依照成员变量现身的风度翩翩意气风发和对齐情势。

  • (1)先为第三个分子dda1分红空间,其早前地址跟结构的开始地址相像(偏巧偏移量0适逢其时为sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;

  • (2)接下去为第三个分子dda分配空间,当时下七个能够分配之处对于组织的开局部址的偏移量为8,是sizeof(char)的翻番,所以把dda存放在偏移量为8的地点满意对齐格局,该成员变量占用sizeof(char)=1个字节;

  • (3)接下去为第多个分子type分配空间,这个时候下二个能够分配之处对于协会的胚胎地址的偏移量为9,不是sizeof(int)=4的倍数,为了知足对齐格局对偏移量的自律难点,VC自动填充3个字节(那四个字节未有放怎么事物),此时下二个得以分配的地址对于组织的最初地址的偏移量为12,凑巧是sizeof(int)=4的翻番,所以把type寄存在偏移量为12的地点,该成员变量占用sizeof(int)=4个字节;
  • 那时整个结构的分子变量已经都分配了上空,总的占用的半空中尺寸为:8 1 3 4=16,正好为结构的字节边界数(即协会中攻克最大空间的等级次序所占用的字节数sizeof(double)=8)的倍数,所以未有空缺的字节必要填写。所以任何结构的大大小小为:sizeof(MyStruct)=8 1 3 4=16,在那之中有3个字节是VC自动填充的,未有遗弃何有含义的事物。

  • (2)示例代码二:调换一下上述例子中MyStruct的分子变量的职位

  • 1 struct MyStruct

    2 {
    3     char dda;
    4     double dda1;
    5     int type;
    6 };
    7 //错:sizeof(MyStruct)=sizeof(double) sizeof(char) sizeof(int)=13。
    8 //对:当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为24。
    

     

  • 注:为地点的布局分配空间的时候,VC依照成员变量现身的逐生龙活虎和对齐方式。

  • (1)先为第二个分子dda分配空间,其在此以前地址跟结构的开场馆址同样(恰好偏移量0刚巧为sizeof(char)的翻番),该成员变量占用sizeof(char)=1个字节;

  • (2)接下去为第三个分子dda1分配空间,此时下贰个能够分配之处对于组织的起初地址的偏移量为1,不是sizeof(double)=8的倍数,需求补足7个字节技艺使偏移量变为8(知足对齐格局),由此VC自动填充7个字节,dda1存放在偏移量为8的地址上,它占用8个字节;

  • (3)接下去为第七个分子type分配空间,这时候下二个能够分配之处对于协会的发端地址的偏移量为16,是sizeof(int)=4的倍数,满足int的对齐方式,所以没有须要VC自动填充,type寄放在偏移量为16的地址上,该成员变量占用sizeof(int)=4个字节; 此时整个结构的分子变量已经都分配了上空,总的占用的空中大小为:1 7 8 4=20,不是结构的节边界数(即组织中攻下最大空间的项目所占用的字节数sizeof(double)=8)的倍数,所以供给填写4个字节,以满意结构的轻重为sizeof(double)=8的倍数。所以该组织总的大小为:sizeof(MyStruct)为1 7 8 4 4=24。个中总的有7 4=拾二个字节是VC自动填充的,未有吐弃何有含义的东西。

  • 字节的对齐形式:

  • 在VC中提供了#pragmapack(n)来设定变量以n字节对齐格局。n字节对齐就是说变量贮存的开地方址的偏移量有二种情景:第生龙活虎,假使n大于等于该变量所占领的字节数,那么偏移量必得知足暗中认可的对齐格局;第二,假若n小于该变量的类型所占领的字节数,那么偏移量为n的翻番,不用满意暗中同意的对齐格局。结构的总大小也许有个节制标准,分上边二种意况:假如n大于全数成员变量类型所并吞的字节数,那么结构的总大小必需为占用空间最大的变量占用的空间数的倍数;不然必须为n的翻番。


注:VC对结构的存储的特殊处理确实提高了CPU存储变量的速度,但有时也会带来一些麻烦,我们也可以屏蔽掉变量默认的对齐方式,自己来设定变量的对齐方式。**
  • (1)示例代码:

     1 #pragmapack(push)//保存对齐状态
     2 
     3 
     4 #pragmapack(4)//设定为4字节对齐
     5 
     6 struct test
     7 {
     8     char m1;
     9     double m4;
    10     int m3;
    11 };
    12 
    13 #pragmapack(pop)//恢复对齐状态
    

     

    注:以上结构的尺寸为16,上面解析其积存情状。

  • (1)首先为m1分配空间,其偏移量为0,餍足大家团结设定的对齐方式(4字节对齐),m1占用1个字节;

  • (2)接着在此以前为m4分配空间,这个时候其偏移量为1,需求补足3个字节,那样使偏移量满足为n=4的翻番(因为sizeof(double)大于n),m4占用8个字节;

  • (3)接着为m3分配空间,那时候其偏移量为12,满意为4的倍数,m3占用4个字节; 那时候早就为具有成员变量分配了上空,共分红了14个字节,满意为n的翻番。假如把地方的#pragmapack(4)改为#pragma pack(8),那么大家得以博得结构的轻重为24。

参考文献: 

[1]《C 全方位学习》范磊——第六章 

[2]《C 程序设计教程(第二版)》钱能——第八章  [3]

 百度找寻关键字:结构体、结构体的法力、结构体的大大小小与内部存储器对齐

本文由pc28.am发布于计算机编程,转载请注明出处:将结构体转为字节流的方式

上一篇:线性关系度量,机器学习 下一篇:没有了
猜你喜欢
热门排行
精彩图文