从结构分配的字节数组上的 C# 指针算法
本文关键字:指针 算法 数组 字节数 结构 分配 字节 | 更新日期: 2023-09-27 18:36:41
来自:
http://www.developerfusion.com/article/84519/mastering-structs-in-c/
建议将结构中的字节数组声明为单个字节,然后使用 FieldOffset 为数组分配内存。分配内存后,可以使用指针算法访问数组。
例:
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 1300)]
public struct TGLProtocolBuffer
{
[FieldOffset(0)]
public byte StartByte;
[FieldOffset(1)]
public byte MessageNumber;
[FieldOffset(2)]
public UInt16 Command;
[FieldOffset(4)]
public UInt32 UnitID;
[FieldOffset(8)]
public UInt16 DataLength;
[FieldOffset(10)]
public byte Data;
};
我想使用 Array.Copy 在此内存上运行,但需要将结构中定义的数组转换为字节到 byte[]
如何将字节转换为字节[]?
你可以在结构中创建一个字节数组,遍历整个事情。(这与C++工会相同)
使用它,您可以访问结构中的每个字节。
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 1300)]
public struct TGLProtocolBuffer
{
[FieldOffset(0)]
public byte[] byteArray; // <--
[FieldOffset(0)]
public byte StartByte;
[FieldOffset(1)]
public byte MessageNumber;
[FieldOffset(2)]
public UInt16 Command;
[FieldOffset(4)]
public UInt32 UnitID;
[FieldOffset(8)]
public UInt16 DataLength;
[FieldOffset(10)]
public byte Data;
};
如果仅Data
字段需要此功能,则可以简单地将其声明为 byte[]
而不是 byte
。
或者,您可以同时使用两者:
[FieldOffset(10)]
public byte Data;
[FieldOffset(10)]
public byte[] DataArray;
您可能需要使用 定义数组大小
public byte[1290] DataArray;
或
[MarshalAs(UnmanagedType.U1, SizeConst=1290)]
你不能将一个字节"投射"到一个字节[],你可以用一个字节创建一个字节[]:
byte b = ...
byte[] ba = new byte[1];
ba[0] = b;
我立即意识到的唯一方法是在不安全的上下文中使用固定字节。这最终将创建一个指向byte*
的指针。使用起来有点奇怪。
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 1300)]
unsafe public struct TGLProtocolBuffer
{
[FieldOffset(0)]
public byte StartByte;
[FieldOffset(1)]
public byte MessageNumber;
[FieldOffset(2)]
public UInt16 Command;
[FieldOffset(4)]
public UInt32 UnitID;
[FieldOffset(8)]
public UInt16 DataLength;
[FieldOffset(10)]
public fixed byte Data[1290];
};
要从数据中获取实际的字节数组,您需要一个帮助程序方法。
unsafe static void GetBytesFromPointer(byte* data, byte[] output)
{
for (int i = 0; i < output.Length; i++)
{
output[i] = data[i];
}
}
然后你应该像这样称呼它。
var data = new byte[1290];
GetBytesFromPointer(tglProtocolBuffer.Data, data);
作为对此的补充,这里有一个测试封送处理的快速小方法。
unsafe public static void Main(string[] args)
{
var data = new byte[1300];
new Random().NextBytes(data);
fixed(byte* dataFixed = data)
{
dataFixed[10] = 0; //add marker byte so we can spot that extracted data starts with a 0 byte
var tglProtocolBuffer = (TGLProtocolBuffer) Marshal.PtrToStructure((IntPtr) dataFixed, typeof (TGLProtocolBuffer));
var bytesFromStruct = new byte[1290];
GetBytesFromPointer(tglProtocolBuffer.Data, bytesFromStruct);
Debug.Assert(bytesFromStruct[0] == 0);
}
}