基本概念:
一、结构体和类的区别?
a、结构体和类最大的区别是一个是值类型(前者),一个是引用类型(后者);
b、比较轻量级的数据可以定义为结构体访问比较快,大一点的用类;
c、结构体中的引用类型要规定大小
二、定义一个结构体?
//StructLayout:微软应许你对类或者结构体的物理布局做调整
//LayoutKind.Sequential:按照结构体字段的排列顺序分配内存空间
//CharSet=CharSet.Ansi:编码方式,这里要选好,不然字符串会出现乱码
//Pack=1:字节对齐方式,1表示一个字节,默认按照4个字节对齐
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi,Pack=1)]
struct SensorHeadInfo
{
public uint cmdId;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=5)]
public byte[] time_t;
public ushort msgLength;
public byte errorFlag;
public byte moduleId;
}
编码实现
一、结构体转Byte[]?
/// <summary>
/// 结构体转byte数组
/// </summary>
/// <param name="data">数据对象</param>
/// <param name="_type">数据类型</param>
/// <returns></returns>
public static byte[] StructToBytes(object data, Type _type)
{
//计算对象长度
int iAryLen = Marshal.SizeOf(_type);
//根据长度定义一个数组
byte[] databytes = new byte[iAryLen];
//在非托管内存中分配一段iAryLen大小的空间
IntPtr ptr = Marshal.AllocHGlobal(iAryLen);
//将托管内存的东西发送给非托管内存上
Marshal.StructureToPtr(data, ptr, true);
//将bytes组数Copy到Ptr对应的空间中
Marshal.Copy(ptr, databytes, 0, iAryLen);
//释放非托管内存
Marshal.FreeHGlobal(ptr);
return databytes;
}
Marshal:这个东西就是C#语言和其他语言相互沟通的桥梁,
C#语言的东西都是托管的(自己的),要把自己的给别个,那就要用这个类
二、Byte[] 转结构体?
/// <summary>
/// byte数组转结构体
/// </summary>
/// <param>byte数组</param>
/// <param>结构体类型</param>
/// <returns>转换后的结构体</returns>
public static object BytesToStuct(byte[] bytes, Type type)
{
//得到结构体的大小
int size = Marshal.SizeOf(type);
//byte数组长度小于结构体的大小
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;
}
保存为索引文件?
public void SaveFile(string FilePath)
{
//给结构体赋值
SensorHeadInfo info;
info.cmdId=1;
info.time_t=new byte[5];
info.msgLength=256;
info.errorFlag=1;
//结构体转byte[]
byte[] bt=StructToBytes(info,info.getType());
using(FileStream fs=new FileStream(FilePath,FileModel.Create,FileAccess.Write))
{
fs.write(bt,0,(int)bt.Length);
}
}
总结
结构体和byte[]数组的转换需要注意一下几点:
1、结构体字节的对齐方式、编码方式、物理布局,结构体的大小
2、转换过程中使用Marshal类
3、能够区分结构体和类,面试的时候能回答上
面试题:一个结构体中有三个字段,两个int,一个Double,请问该结构体占多少字节?
答:int:4个字节,double:8个字节,所以是4+4+8=16 (不完全正确)
分析:字段排序不同则出现的情况不一样
16字节
24字节
内存分配时:默认按照最大的类型字节数来分配字节块,两幅图最大的都是8字节
第一图:ID和Age一共合在一起8个字节刚刚好,后面的Grade是8字节,一共16字节
第二图:ID是4个字节,但是第二个Grade就是8字节,Grade把ID 和Age都分开了,所以其他两个都要补齐,一共24字节