0

从:

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 对此内存进行操作,但需要将结构中定义的数组转换为字节到字节 []

如何将字节转换为字节 []?

4

3 回答 3

2

您可以在结构中创建一个字节数组,遍历整个内容。(这与 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)]
于 2013-10-23T08:47:22.523 回答
0

您不能将一个字节“转换”为一个字节 [],您可以用一个字节制作一个字节 []:

byte b = ...
byte[] ba = new byte[1];
ba[0] = b;
于 2013-10-23T08:28:51.200 回答
0

我立即意识到的唯一方法是在不安全的上下文中使用固定字节。这将最终创建一个指向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);
    }
}
于 2013-10-23T08:49:51.360 回答