运行此代码时:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace StructLayoutTest
{
class Program
{
unsafe static void Main()
{
Console.WriteLine(IntPtr.Size);
Console.WriteLine();
Sequential s = new Sequential();
s.A = 2;
s.B = 3;
s.Bool = true;
s.Long = 6;
s.C.Int32a = 4;
s.C.Int32b = 5;
int* ptr = (int*)&s;
Console.WriteLine(ptr[0]);
Console.WriteLine(ptr[1]);
Console.WriteLine(ptr[2]);
Console.WriteLine(ptr[3]);
Console.WriteLine(ptr[4]);
Console.WriteLine(ptr[5]);
Console.WriteLine(ptr[6]);
Console.WriteLine(ptr[7]); //NB!
Console.WriteLine("Press any key");
Console.ReadKey();
}
[StructLayout(LayoutKind.Explicit)]
struct Explicit
{
[FieldOffset(0)]
public int Int32a;
[FieldOffset(4)]
public int Int32b;
}
[StructLayout(LayoutKind.Sequential, Pack …Run Code Online (Sandbox Code Playgroud) 首先,布尔类型被称为具有四字节值的默认编组类型.以下代码有效:
struct A
{
public bool bValue1;
public int iValue2;
}
struct B
{
public int iValue1;
public bool bValue2;
}
public static void Main()
{
int[] rawvalues = new int[] { 2, 4 };
A a = (A)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(A));
Assert.IsTrue(a.bValue1 == true);
Assert.IsTrue(a.iValue2 == 4);
B b = (B)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(B));
Assert.IsTrue(b.iValue1 == 2);
Assert.IsTrue(b.bValue2 == true);
}
Run Code Online (Sandbox Code Playgroud)
显然,这些结构独立编组就好了.值按预期转换.但是,当我们将这些结构组合成一个"联合"时,通过声明LayoutKind.Explicit,如下所示:
[StructLayout(LayoutKind.Explicit)]
struct Broken
{
[FieldOffset(0)]
public A a;
[FieldOffset(0)]
public B b;
}
Run Code Online (Sandbox Code Playgroud)
我们突然发现自己无法正确编组这些类型.以下是上述结构的测试代码及其失败方式:
int[] rawvalues = new int[] …Run Code Online (Sandbox Code Playgroud) 我有一个结构,其中一个非重叠字段报告为重叠.
[FieldOffset(8)]
Int32 X;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
[FieldOffset(12)]
string Y;
[FieldOffset(28)]
int Z;
Run Code Online (Sandbox Code Playgroud)
报告的错误是:
无法加载类型'XXX'...它包含偏移12处的对象字段,该字段未正确对齐或由非对象字段重叠.
它仅在Release配置中发生(TRACE,DEBUG标志和不安全代码被启用,优化被关闭),猜测 - 它会发生什么?
UPD:感谢@svick.确认x64构建不是人们想要的编组.
我尝试使用 构建一个 struct ( SA) [StructLayout(LayoutKind.Explicit)],它有一个字段是另一个struct( SB)。
首先:我很惊讶我被允许声明其他结构没有[StructLayout(LayoutKind.Explicit)],而在SA,所有字段都必须有[FieldOffset(0)],否则编译器会大喊大叫。这没有多大意义。
第二:似乎所有的 reference( object) 字段SB都移到了SB.
:)注意:我不打算在生产代码中使用它。我问这个问题主要是出于好奇。
// No object fields in SB
// Gives the following layout (deduced from experimentation with the C# debugger):
// | f0 | f4 and i | f8 and j | f12 and k | f16 |
[StructLayout(LayoutKind.Explicit)]
struct SA …Run Code Online (Sandbox Code Playgroud) c# ×4
.net ×2
marshalling ×2
boolean ×1
offset ×1
pinvoke ×1
struct ×1
structlayout ×1
unsafe ×1