Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.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# 如何使用固定数组将数组复制到结构?_C# - Fatal编程技术网

C# 如何使用固定数组将数组复制到结构?

C# 如何使用固定数组将数组复制到结构?,c#,C#,将“mydata”复制到“sample_a”的最佳方式是什么 我希望在样本数组[1]中得到4个。这个值是p[9] 我计划将其用于TCP/UDP数据包通信 [StructLayout(LayoutKind.Sequential, Pack = 1)] struct SampleA { public int data1; public int data2; public unsafe fixed char data_array[3]; public int data3

将“mydata”复制到“sample_a”的最佳方式是什么

我希望在样本数组[1]中得到4个。这个值是p[9]

我计划将其用于TCP/UDP数据包通信

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    public unsafe fixed char data_array[3];
    public int data3;
}

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");

    short bytesize = 15; 
    byte[] mydata = new byte[bytesize];
    unsafe
    {
        fixed (byte* p = mydata)
        {
            // data1
            p[0] = 1;
            // data2
            p[4] = 2;
            // data_array
            p[8] = 3;
            p[9] = 4;
            p[10] = 5;
            // data3
            p[11] = 6;
        }

        // Copy 'mydata' to 'sample_a'
        IntPtr intptr = Marshal.AllocHGlobal(bytesize);
        Marshal.Copy(mydata, 0, intptr, bytesize);
        SampleA sample_a = (SampleA)Marshal.PtrToStructure(intptr, typeof(SampleA));
        Marshal.FreeHGlobal(intptr);

        // I want to get 4 in a1
        int a1 = (int)sample_a.data_array[1];
    }
}

您的问题是C#的字符有2个字节宽,而您将其视为1个字节宽

一种修复方法是显式地将它们声明为
字节

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    public unsafe fixed byte data_array[3];
    public int data3;
}
使用
非托管类型嵌入数组更为常见。ByValArray

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] data_array;
    public int data3;
}
如果要使用
char
,可以告诉封送员每个字符都应该作为
U8
封送:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U8)]
    public char[] data_array;
    public int data3;
}
您还可以告诉封送拆收器您正在使用ANSI字符串,这具有相同的效果

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public char[] data_array;
    public int data3;
}
你的问题是C#的字符有2个字节宽,你把它们当作1个字节宽

一种修复方法是显式地将它们声明为
字节

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    public unsafe fixed byte data_array[3];
    public int data3;
}
使用
非托管类型嵌入数组更为常见。ByValArray

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] data_array;
    public int data3;
}
如果要使用
char
,可以告诉封送员每个字符都应该作为
U8
封送:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U8)]
    public char[] data_array;
    public int data3;
}
您还可以告诉封送拆收器您正在使用ANSI字符串,这具有相同的效果

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public char[] data_array;
    public int data3;
}

在这里,您可以避免使用跨距进行大量工作:


//注:尺寸为18;如果您想要15-也许更改char=>byte
byte[]mydata=新字节[Unsafe.SizeOf()];
//备选方案:Span mydata=stackalloc字节[Unsafe.SizeOf()];
//…TODO:填充mydata
//扔掉它
var sample_a=MemoryMarshal.Cast(mydata)[0];
您也可以使用不安全的
。如
,但这不是一个好主意,因为它也不会检测不正确的内存状况:

var sample_a=Unsafe.As(参考mydata[0]);

在这里,您可以避免使用跨距进行大量工作:


//注:尺寸为18;如果您想要15-也许更改char=>byte
byte[]mydata=新字节[Unsafe.SizeOf()];
//备选方案:Span mydata=stackalloc字节[Unsafe.SizeOf()];
//…TODO:填充mydata
//扔掉它
var sample_a=MemoryMarshal.Cast(mydata)[0];
您也可以使用不安全的
。如
,但这不是一个好主意,因为它也不会检测不正确的内存状况:

var sample_a=Unsafe.As(参考mydata[0]);

您也可以检查“这不做内存复制”。谢谢。我检查你的链接。你也可以检查这个不做内存拷贝。谢谢。我检查你的链接。谢谢你的回答!这是实现这一目标的几种方法之一;然而,这并不是你唯一的答案!这是实现这一目标的几种方法之一;但是,它不是唯一的选项注意,它不使用封送拆收器,因此通常影响封送拆收器的属性(例如
marshallas
)都不会起任何作用。@canton7不正确
StructLayout
也会影响结构本身的布局:所以是的,它仍然有效(它不会影响
Marshallas
——不过这是一个注释编辑!)在我这方面,这是一个真实的、糟糕的例子。已更改。@canton7 re字节与字符:是的,这是真的;如果OP希望这些是字节:它们应该将它们声明为字节。请注意,这并不使用封送拆收器,因此通常影响封送拆收器的属性(例如,
marshallas
)都不会起任何作用。@canton7不正确
StructLayout
也会影响结构本身的布局:所以是的,它仍然有效(它不会影响
Marshallas
——不过这是一个注释编辑!)在我这方面,这是一个真实的、糟糕的例子。已更改。@canton7 re字节与字符:是的,这是真的;如果OP希望这些是字节:他们应该将它们声明为字节