我已经看到了许多将 byte[] 复制到结构的方法,反之亦然。但是,我想知道是否可以将 byte[] 指针转换为结构(就像你在 C 中所做的那样)..
我希望能够将 byte[] 转换为 struct,对 struct 进行更改,并让更改自动出现在 byte[] 中。
谢谢,礼萨
您只需投射指针(有时您需要void*
在中间经过):
struct Foo
{
public int Bar;
}
static unsafe void Main()
{
byte[] buffer = new byte[10];
fixed (byte* untyped = buffer)
{
var typed = (Foo*)untyped;
typed[0].Bar = 123;
}
// buffer has the changes
}
如果您需要偏移到缓冲区中,请使用byte* untyped = &buffer[offset]
.
如果你想要一个原始结构指针,那么:
fixed (byte* ptr = buffer)
{
var typed = (Foo*)ptr;
Foo* foo = &typed[0];
foo->Bar = 123;
}
但是,请注意,您不能将 a 传递Foo*
给期望 aFoo
或的方法ref Foo
。
我发现这种方法是实现我想要的最简单的方法。如果您定义结构以使 byte[] 与元素重叠,则副本在 struct 和 byte[] 之间是有效透明的(假设字节序是您的期望;在我的情况下,它是)。
[StructLayout(LayoutKind.Explicit)]
public unsafe struct ListEntry {
[System.Runtime.InteropServices.FieldOffset(0)] public fixed byte raw[512];
[System.Runtime.InteropServices.FieldOffset(0)] public byte version;
[System.Runtime.InteropServices.FieldOffset(1)] public UInt16 magic;
[System.Runtime.InteropServices.FieldOffset(3)] public UInt32 start_time;
[System.Runtime.InteropServices.FieldOffset(7)] public UInt16 run_id;
[System.Runtime.InteropServices.FieldOffset(9)] public UInt16 channels;
[System.Runtime.InteropServices.FieldOffset(11)] public UInt16 sampling_rate;
[System.Runtime.InteropServices.FieldOffset(13)] public UInt32 start_sector;
[System.Runtime.InteropServices.FieldOffset(510)] public UInt16 checksum;
}
我建议你最好的选择,如果速度不是关键,可能是将数据存储在 a 中byte[]
,并有一个类,该类包含对该数据的不可变引用,byte[]
并具有其 get/set 方法访问数组的属性。属性获取/设置将始终反映并反映在数组的状态中,因为数组本身将保存对象的状态。不需要“不安全”代码。
方法可能看起来像:
public static class IntPack
{ // All methods ssume unchecked arithmetic
public static Int16 FetchI16LE(this byte[] dat, int offset)
{
return (Int16)(dat[offset] + (dat[offset + 1] << 8));
}
public static Int32 FetchI32LE(this byte[] dat, int offset)
{
return dat[offset] + (dat[offset + 1] << 8) +
(dat[offset + 2] << 16) + (dat[offset + 3] << 24);
}
public static void StuffI16LE(this byte[] dat, int offset, int value)
{
dat[offset] = (byte)(value);
dat[offset+1] = (byte)(value >> 8);
}
public static void StuffI32LE(this byte[] dat, int offset, int value)
{
dat[offset] = (byte)(value);
dat[offset + 1] = (byte)(value >> 8);
dat[offset + 2] = (byte)(value >> 16);
dat[offset + 3] = (byte)(value >> 24);
}
}
指示的方法假定小端顺序。可以很容易地为大端编写相应的 __BE 方法方法。