C# 如何使用固定数组将数组复制到结构?
将“mydata”复制到“sample_a”的最佳方式是什么 我希望在样本数组[1]中得到4个。这个值是p[9] 我计划将其用于TCP/UDP数据包通信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
[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希望这些是字节:他们应该将它们声明为字节