包含数组的Struct数组

时间:2016-12-02 23:56:31

标签: c# visual-studio-2010

我是C#的野蛮人,我看过以前类似的问题的答案,但仍然卡住了。我需要收集并处理包含ushort数组的3个结构数组。我创建了一个类来保存我的结构:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

struct Wvsamps
{
    ushort[] wav1 = new ushort[3];
    ushort[] wav2 = new ushort[3];
    ushort[] wav3 = new ushort[3];
    ushort[] wav4 = new ushort[3];
    ushort modes;
    uint time;
    ushort chkSum;
}       


namespace ConsoleApplication1
{
    public class LoadSamps
    {
        Wvsamps[] ldSamps = new Wvsamps[0x800000];
    }
}

编译器给出错误:

Error   1   'Wvsamps.wav1': cannot have instance field initializers in structs  C:\Users\Hewitt\Desktop\C# Projects\MarshalBytesToStruct\LoadSamps.cs   8   11  MarshalBytesToStruct

然后我想从我的Main程序类中访问并将值放入我的结构数组中。我正在将其作为一个控制台应用程序来尝试在Windows窗体应用程序中获取此操作。

为了扩展我的问题,我将通过网络连接以1 /秒的速度接收32字节数据包。 32字节数据包中的实际数据如下所示:

0x94, 0xa5, 0xca, 0x62, 0x41, 0x28, 0x4c, 0x93, 0x09, 0x42, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x01, 0x40, 0x10, 0x00, 0x00, 0x70, 0x0d, 0x58, 0x3e, 0xc6, 0xd1, 0x07,

当我收到这些32字节的数据包时,我需要将它们放在Wvsamps结构的数组中,如我原来的帖子所示。理想情况下,Wvsamps结构长度为32bytes。在旧的C / C ++嵌入式解决方案中,我能够将32byte网络数据包存储到ldSamps数组中的Wvsamps结构,然后将ldSamps数组索引递增为指向下一个接收数据包的ldSamps数组中的下一个可用Wvsamps结构。我需要在ldSamps数组中累积值为0x40000的Wvsamps结构,因此数组需要为0x40000 Wvsamps结构长。

我将从ldSamps数组访问Wvsamps结构以在WinForm中绘制波形,滚动波形(我至少使用硬编码模拟数据)并进行测量。还会有一个额外的问题,即我收到的数据采用Big Endian格式,需要转换并存储在Wvsamps结构中的Little Endian中。

3 个答案:

答案 0 :(得分:1)

这是一个使用fixed数组的解决方案,它会很快但很笨重。

[StructLayout(LayoutKind.Sequential)]
unsafe struct Wvsamps
{
    const int Size = 3;
    fixed ushort wav1[Size];
    fixed ushort wav2[Size];
    fixed ushort wav3[Size];
    fixed ushort wav4[Size];
    public ushort modes;
    public uint time;
    public ushort chkSum;

    public ushort this[int wav, int index]
    {
        get
        {
            if (index<0||index>=Size)
            {
                throw new IndexOutOfRangeException("index");
            }
            switch (wav)
            {
                case 0:
                    fixed (ushort* ptr = wav1) { return ptr[index]; }
                case 1:
                    fixed (ushort* ptr = wav2) { return ptr[index]; }
                case 2:
                    fixed (ushort* ptr = wav3) { return ptr[index]; }
                case 3:
                    fixed (ushort* ptr = wav4) { return ptr[index]; }
                default:
                    throw new IndexOutOfRangeException("wav");
            }
        }
        set
        {
            if (index<0||index>=Size)
            {
                throw new IndexOutOfRangeException("index");
            }
            switch (wav)
            {
                case 0:
                    fixed (ushort* ptr = wav1) { ptr[index]=value; }
                    break;
                case 1:                                    
                    fixed (ushort* ptr = wav2) { ptr[index]=value; }
                    break;
                case 2:                                    
                    fixed (ushort* ptr = wav3) { ptr[index]=value; }
                    break;
                case 3:                                    
                    fixed (ushort* ptr = wav4) { ptr[index]=value; }
                    break;
                default:
                    throw new IndexOutOfRangeException("wav");
            }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Wvsamps[] ldSamps = new Wvsamps[0x800000];            

        for (int i = 0; i<ldSamps.Length; i++)
        {
            Wvsamps sample=new Wvsamps();

            sample.time=(uint)i;
            sample.modes=1;
            //wav1 = [1,2,3]
            sample[0, 0]=1;
            sample[0, 1]=2;
            sample[0, 2]=3;
            //wav2 = [4,5,6]
            sample[1, 0]=4;
            sample[1, 1]=5;
            sample[1, 2]=6;
            //wav3 = [7,8,9]
            sample[2, 0]=7;
            sample[2, 1]=8;
            sample[2, 2]=9;
            //wav4 = [10,11,12]
            sample[3, 0]=10;
            sample[3, 1]=11;
            sample[3, 2]=12;

            // VERY IMPORTANT
            // Structs needs to be assigned with one statement as a whole
            ldSamps[i]=sample;

            // You cannot do this, ldSamps[i].time = 10
        }
    }
}

答案 1 :(得分:1)

更简单的方法可能是,不要在结构内部使用数组,而是声明相应的变量(wav11,wav12,wav13,wav21 ......)。

[StructLayout(LayoutKind.Sequential)]
[ImmutableObject(true)]
public struct Wvsamps
{
    const int Size = 3;
    public readonly ushort wav11, wav12, wav13;
    public readonly ushort wav21, wav22, wav23;
    public readonly ushort wav31, wav32, wav33;
    public readonly ushort wav41, wav42, wav43;
    public readonly ushort modes;
    public readonly uint time;
    public readonly ushort chkSum;

    public Wvsamps(uint time, ushort modes,
        ushort wav11, ushort wav12, ushort wav13,
        ushort wav21, ushort wav22, ushort wav23,
        ushort wav31, ushort wav32, ushort wav33,
        ushort wav41, ushort wav42, ushort wav43,
        ushort chkSum)
    {
        this.time=time;
        this.modes=modes;
        this.wav11=wav11;
        this.wav12=wav12;
        this.wav13=wav13;
        this.wav21=wav21;
        this.wav22=wav22;
        this.wav23=wav23;
        this.wav31=wav31;
        this.wav32=wav32;
        this.wav33=wav33;
        this.wav41=wav41;
        this.wav42=wav42;
        this.wav43=wav43;
        this.chkSum=chkSum;
    }

}

public class Samples
{
    public const int Size = 0x800000;

    readonly Wvsamps[] sample1, sample2, sample3;

    public Samples()
    {
        sample1=new Wvsamps[Size];
        sample2=new Wvsamps[Size];
        sample3=new Wvsamps[Size];
    }

    public Wvsamps[] Sample1 { get { return sample1; } }
    public Wvsamps[] Sample2 { get { return sample2; } }
    public Wvsamps[] Sample3 { get { return sample3; } }
}


class Program
{
    static void Main(string[] args)
    {
        Samples data = new Samples();

        for (int i = 0; i<Samples.Size; i++)
        {
            data.Sample1[i]=new Wvsamps((uint)i, 1,
                1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
                78);
            // Similarly data.Sample2[i]= ... 
        }
    }
}

答案 2 :(得分:0)

这是一个使用本机数组的解决方案,因为为每个实例创建了四个新数组,并且数组的内容散布在RAM周围,因此速度较慢。当内存尽可能本地化时,现代处理器的工作速度最快。

[StructLayout(LayoutKind.Sequential)]    
struct Wvsamps
{
    const int Size = 3;
    public readonly ushort[] wav1;
    public readonly ushort[] wav2;
    public readonly ushort[] wav3;
    public readonly ushort[] wav4;
    public readonly ushort modes;
    public readonly uint time;
    ushort chkSum;

    public Wvsamps(uint time, ushort modes)
    {
        this.time=time;
        this.modes=modes;
        this.wav1=new ushort[Size];
        this.wav2=new ushort[Size];
        this.wav3=new ushort[Size];
        this.wav4=new ushort[Size];
        this.chkSum=0;
    }

    public void CalcChecksum()
    {
        this.chkSum=0;
        for (int i = 0; i<Size; i++)
        {
            chkSum=(ushort)((chkSum+wav1[i]+wav2[i]+wav3[i]+wav4[i])%256);
        }
    }

    public ushort Checksum { get { return chkSum; } }
}

class Program
{
    static void Main(string[] args)
    {
        Wvsamps[] ldSamps = new Wvsamps[0x800000];            

        for (int i = 0; i<ldSamps.Length; i++)
        {
            // The constructor initializes the arrays also
            Wvsamps sample=new Wvsamps( (uint)i, 1);

            //wav1 = [1,2,3]
            sample.wav1[0]=1;
            sample.wav1[1]=2;
            sample.wav1[2]=3;
            //wav2 = [4,5,6]
            sample.wav2[0]=4;
            sample.wav2[1]=5;
            sample.wav2[2]=6;
            //wav3 = [7,8,9]
            sample.wav3[0]=7;
            sample.wav3[1]=8;
            sample.wav3[2]=9;
            //wav4 = [10,11,12]
            sample.wav4[0]=10;
            sample.wav4[1]=11;
            sample.wav4[2]=12;

            sample.CalcChecksum();

            // VERY IMPORTANT
            // Structs needs to be assigned with one statement as a whole
            ldSamps[i]=sample;

            // You cannot do this: ldSamps[i].time = 10;
        }

        var checksum = ldSamps[1000].Checksum;
    }
}

修改1

通过删除数组定义中的readonly,您可以使用一个语句分配值。同样,这取决于你想要做什么,在预先分配数组方面。

[StructLayout(LayoutKind.Sequential)]
struct Wvsamps
{
    const int Size = 3;
    public ushort[] wav1;
    public ushort[] wav2;
    public ushort[] wav3;
    public ushort[] wav4;
    public readonly ushort modes;
    public readonly uint time;
    ushort chkSum;

    public Wvsamps(uint time, ushort modes)
    {
        this.time=time;
        this.modes=modes;
        this.wav1=null;
        this.wav2=null;
        this.wav3=null;
        this.wav4=null;
        this.chkSum=0;
    }

        for (int i = 0; i<ldSamps.Length; i++)
        {
            Wvsamps sample = new Wvsamps((uint)i, 1);
            sample.wav1=new ushort[] { 1, 2, 3 };
            sample.wav2=new ushort[] { 4, 5, 6 };
            sample.wav3=new ushort[] { 7, 8, 9 };
            sample.wav4=new ushort[] { 10, 11, 12 };

        }