Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# StructLayout将字节数组转换为短字符_C#_Bytearray_Structlayout - Fatal编程技术网

C# StructLayout将字节数组转换为短字符

C# StructLayout将字节数组转换为短字符,c#,bytearray,structlayout,C#,Bytearray,Structlayout,很抱歉这个糟糕的标题,但我真的知道我想要什么,也知道什么是错的 基本上我有一个结构(我有250多个结构,但它们都遵循相同的想法),看起来像这样: [StructLayout(LayoutKind.Explicit)] public struct GenericPacket { [FieldOffset(0)] public byte[] data; [FieldOffset(0)] public short packetid; } 问题是字节数组是一种引用类型

很抱歉这个糟糕的标题,但我真的知道我想要什么,也知道什么是错的

基本上我有一个结构(我有250多个结构,但它们都遵循相同的想法),看起来像这样:

[StructLayout(LayoutKind.Explicit)]
public struct GenericPacket
{
    [FieldOffset(0)]
    public byte[] data;

    [FieldOffset(0)]
    public short packetid;
}
问题是字节数组是一种引用类型,而short是一种值类型,它不允许将fieldoffset设置为相同的内存位置

我真的很不愿意删除我写的所有结构,只是为了用另一种方式。所以我的问题是,我怎样才能用一种有效的方式来使用它。基本上我要做的是:

socket.Receive(buff, 0, 0, SocketFlags.None);
GenericPacket packet = new GenericPacket();
packet.data = buff;
Console.WriteLine(packet.packetid);
它甚至拒绝编译,因为它不想生成struct/:

在任何人提出其他方法之前,我这样做的原因是它需要超高速。。。我可以使用ByteReader和其他方法(如位转换器),但它需要比这快一点

我从按位移位开始,但我需要一种更“动态”的方式来完成,因为在我有一个数据包ID后,我用另一个结构读取它,例如:

[StructLayout(LayoutKind.Explicit)]
public struct _03k
{
    [FieldOffset(0)]
    byte[] data;

    [FieldOffset(0)]
    short packetid;
    [FieldOffset(2)]
    short @null;
    [FieldOffset(4)]
    int major;
    [FieldOffset(8)]
    int minor;
    [FieldOffset(12)]
    int build;
}
我不需要有很多内联的“按位屎”,我只需要一个简单且非常快速的方法来实现这一点。。。看来我跑得很快但不容易

请帮忙!不安全代码是可以的,但也更喜欢托管版本

失败:(:刚刚记住,您可以通过装箱(强制转换为类型对象)将值类型转换为引用类型。但是,这确实会删除真正的返回类型,并说它只是一个对象,XML文档中是否有关于返回类型的谎言? 不起作用,D:

更新:好的,现在我有:

public struct GenericPacket
{
    public short packetid;

    public static GenericPacket ReadUsingPointer(byte[] data)
    {
        unsafe
        {
            fixed (byte* packet = &data[0])
            {
                return *(GenericPacket*)packet;
            }
        }
    }
}
但是每次都要调用一个方法来转换它,这有点烦人:(有人有更多的建议吗


谢谢,JD在本例中,您可以这样做:

[StructLayout(LayoutKind.Explicit)]
struct byte_array
{
    [FieldOffset(0)]
    public byte byte1;

    [FieldOffset(1)]
    public byte byte2;

    [FieldOffset(0)]
    public short packetid;
}

但一般来说,Buffer.BlockCopy可能是一个更好的解决方案。

您只想将数组的前两个字节转换为短字节,这会带来什么性能问题

packetid = ((short)data[0]  << 8) | data[1];

packetid=((short)data[0]我最终确定的是一个带有隐式转换运算符的结构,该运算符调用ReadByPointer方法

public struct GenericPacket
{
    public short packetid;

    public static GenericPacket ReadUsingPointer(byte[] data)
    {
        unsafe
        {
            fixed (byte* packet = &data[0])
            {
                return *(GenericPacket*)packet;
            }
        }
    }

    static public implicit operator GenericPacket(byte[] value) 
    {
        return GenericPacket.ReadUsingPointer(value);
    }
}
这允许您执行以下操作:

GenericPacket packet = bufferFromReceive;

谢谢-jD

我刚刚发现您可以在结构中使用fixed Arays:

[StructLayout(LayoutKind.Explicit)]
unsafe struct Union
{
    [FieldOffset(0)]
    public short x;
    [FieldOffset(0)]
    public fixed byte y[2];
}
初始化:

var u = new Union();
byte[] y = new byte[2]; //your original array here
int len = y.Length;
unsafe
{
    fixed (byte* s= y)
    {
        byte* source = s;
        byte* dest = u.y;
        for (int i = 0; i < len; i++)
        {
            *dest++ = *source++;
        }
    }
}
var u=newunion();
byte[]y=新字节[2];//此处是原始数组
int len=y.长度;
不安全的
{
固定(字节*s=y)
{
字节*源=s;
字节*dest=u.y;
对于(int i=0;i
什么是blahblah?int?SocketFlags?SocketError?这类事情在C中可能会起作用,但我认为在.NET中没有办法做到这一点-我不认为有任何关于字节布局的保证,例如short是什么,或者endianness。@Damien_不相信我自己在管理所有的endianness,所以我知道它是正确的^^我似乎无法确定的是什么o是让字节数组与非引用类型一起正常工作…我在某个地方听说,可以使用固定字节的不安全代码,但无法使其正常工作。例如,请参见以下答案:是的,我知道它可以工作,但字节数组长度不同,我不希望在arr时必须设置成百上千个字节ay是为这类事情而设计的。关于块复制,问题不是将字节放入结构中的数组中,而是让它进行编译,因为它不会让数组和值类型的内存位置重叠。是的,但这是多步骤等式中的第一步,这个简单的方法允许我获取packetID并在一个切换到看到另一个结构的布局我有…我已经更新了这个问题。感谢protobuff的想法,我的朋友今天早上告诉我,在我们运行这个东西之后,可能值得研究一下!无论如何,谢谢兄弟:)这很好,但是如何帮助OP?他没有提到他需要一个“固定大小数组”。是的,但它不会隐式地将字节[]转换为字节*如何使用它?我只是在尝试将字节[]分配给字节*时出错!请帮助,因为这似乎是唯一的方法:(由于它是一个固定数组,您无法为其分配指针或引用。您必须将源数组内容一个字节一个字节地复制到固定数组中。