2

我已经看到了许多将 byte[] 复制到结构的方法,反之亦然。但是,我想知道是否可以将 byte[] 指针转换为结构(就像你在 C 中所做的那样)..

我希望能够将 byte[] 转换为 struct,对 struct 进行更改,并让更改自动出现在 byte[] 中。

谢谢,礼萨

4

3 回答 3

1

您只需投射指针(有时您需要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

于 2012-10-21T22:15:16.783 回答
0

我发现这种方法是实现我想要的最简单的方法。如果您定义结构以使 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;
    }
于 2012-10-22T19:27:20.543 回答
0

我建议你最好的选择,如果速度不是关键,可能是将数据存储在 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 方法方法。

于 2012-10-22T23:02:19.303 回答