【发布时间】:2019-11-11 18:57:17
【问题描述】:
我正在编写代码来解析数据包。
我想改变数组的引用地址,但是不知道如何在不使用指针的情况下改变引用地址。 如果我复制数组的一部分,我认为它会变慢。如果我使用指针,那将是不安全的。
下面是我正在写的代码。
public class Datagrams : LinkedList<DatagramPacket>
{
public Datagrams(byte[] RowData) : base()
{
AddLast(new DatagramPacket(RowData));
while(Last.Value.header.Length.LastIndicator)
{
///////////////////////////////////////////
//I want do that. But this is unsafe code//
///////////////////////////////////////////
AddLast(new DatagramPacket( RowData + sizeof[Last.Value] ));
}
}
}
public class DatagramPacket : Packet
{
public enum DatagramCmd : Byte
{
NOP = 0x0,
APRD = 0x1,
APWR = 0x2,
APRW = 0x3,
FPRD = 0x4,
FPWR = 0x5,
FPRW = 0x6,
BRD = 0x7,
BWR = 0x8,
BRW = 0x9,
LRD = 0xA,
LWR = 0xB,
LRW = 0xC,
ARMW = 0xD,
FRMW = 0xE
}
[StructLayout(LayoutKind.Explicit)]
public struct DatagramAddr
{
[MarshalAs(UnmanagedType.U4), FieldOffset(0)]
public UInt32 LogicalAddr;
[MarshalAs(UnmanagedType.U2), FieldOffset(0)]
public UInt16 SlaveAddr;
[MarshalAs(UnmanagedType.U2), FieldOffset(2)]
public UInt16 OffsetAddr;
}
public struct DatagramLength
{
[MarshalAs(UnmanagedType.U2)]
public UInt16 bits;
public int Length { get => bits & 0x07FF; }
public bool Valid { get => (bits & 0x0380) == 0; }
public bool RoundTrip { get => (bits & 0x4000) != 0; }
public bool LastIndicator { get => (bits & 0x8000) != 0; }
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DatagramHeader
{
[MarshalAs(UnmanagedType.U1)]
public DatagramCmd Cmd;
[MarshalAs(UnmanagedType.U1)]
public Byte Index;
[MarshalAs(UnmanagedType.Struct)]
public DatagramAddr Addr;
[MarshalAs(UnmanagedType.Struct)]
public DatagramLength Length;
[MarshalAs(UnmanagedType.U2)]
public UInt16 Interrupt;
}
public DatagramHeader header;
public UInt16 wc; //Working Count
public DatagramPacket(byte[] RowData) : base(RowData)
{
header = new DatagramHeader();
GCHandle handle = GCHandle.Alloc(RowData, GCHandleType.Pinned);
try
{
header = (DatagramHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DatagramHeader));
}
finally
{
handle.Free();
}
body = new byte[header.Length.Length];
Buffer.BlockCopy(RowData, Marshal.SizeOf<DatagramHeader>(), body, 0, body.Length);
wc = BitConverter.ToUInt16(RowData, Marshal.SizeOf<DatagramHeader>() + body.Length);
}
public override Packet Parse()
{
throw new NotImplementedException();
}
}
有没有不使用指针改变引用的方法?
【问题讨论】:
-
你忘记了你在
.net。您的代码“设计”很慢,因为它是托管的。因此,这种微优化可能只会比加速造成更大的伤害。但如果你 100% 确定 - 有一个 ref keyword。 -
我使用了类似“ref &RowData[Marshal.SizeOf(Last.Value)]”和“ref RowData + Marshal.SizeOf(Last.Value)”的 ref,但无法编译。如何使用 ref 关键字?
-
public DatagramPacket(ref byte[] RowData) : base(RowData) -
很自然的,我将ref关键字应用到了构造函数的参数上并编译了它。但是,由于与fixed一起使用时出现编译错误,因此无法使用。既然fixed也是不安全的,我觉得和使用指针没什么区别。