C#中如何高效将字节数组复制到结构体数组?
快速将字节数组复制到结构体数组的实现方案
针对你的需求,这里提供两种高效的实现方式,优先推荐内存指针直接复制的unsafe方案(速度最快);如果无法启用unsafe代码,可使用Marshal类的替代方案。
方案一:Unsafe内存指针复制(性能最优)
这种方式直接操作内存块,完全避免额外的类型转换开销,是性能最优的选择。需要先在项目属性中勾选「允许不安全代码」。
asVarGroups = new TsVarGroup[sVarTable.Count]; // 自动获取结构体大小,避免硬编码错误 int structSize = Marshal.SizeOf<TsVarGroup>(); byte[] dataVarGroups = Connection.GETMEM("R", (sVarTable.Addr - ADDRESS_OFFSET), asVarGroups.Length * structSize); unsafe { fixed (byte* srcPtr = dataVarGroups) fixed (TsVarGroup* destPtr = asVarGroups) { // 直接复制整个内存块 Buffer.MemoryCopy(srcPtr, destPtr, asVarGroups.Length * structSize, dataVarGroups.Length); } }
原理:你的结构体已标记LayoutKind.Sequential和Pack=1,内存布局与字节数组完全对齐,通过指针直接复制内存即可完成批量转换,fixed数组NamePrefix的内容会被完整复制,后续调用GetNamePrefix()可正常获取字符串。
方案二:Marshal类转换(无需unsafe)
如果项目无法启用unsafe代码,可使用Marshal类完成内存块到结构体的转换,性能略低于unsafe方案,但实现简单。
asVarGroups = new TsVarGroup[sVarTable.Count]; int structSize = Marshal.SizeOf<TsVarGroup>(); byte[] dataVarGroups = Connection.GETMEM("R", (sVarTable.Addr - ADDRESS_OFFSET), asVarGroups.Length * structSize); // 固定字节数组,避免GC移动内存 GCHandle dataHandle = GCHandle.Alloc(dataVarGroups, GCHandleType.Pinned); try { IntPtr srcBasePtr = dataHandle.AddrOfPinnedObject(); for (int i = 0; i < asVarGroups.Length; i++) { // 逐个将内存块转换为结构体 asVarGroups[i] = Marshal.PtrToStructure<TsVarGroup>(srcBasePtr + i * structSize); } } finally { // 释放固定句柄 dataHandle.Free(); }
关键注意事项
- 务必使用
Marshal.SizeOf<TsVarGroup>()获取结构体大小,不要硬编码TS_VARGROUP_SIZE,避免结构体修改后出现大小不匹配的问题。 - 保持结构体的
StructLayout设置不变(Sequential+Pack=1),确保内存布局与字节流完全一致,无额外对齐填充。
内容的提问来源于stack exchange,提问作者jirikk
相关产品推荐
相关产品推荐

