马歇尔.c#应用程序中的sizeof和structure

本文关键字:sizeof structure 应用程序 马歇尔 | 更新日期: 2023-09-27 18:19:01

我想在我的应用程序中使用marshal . sizeof()方法

class Class1
{
    static void Main()
    {
        Console.WriteLine("Number of bytes needed by a PointB object: {0}",
      Marshal.SizeOf(typeof(PointB)));
        Console.WriteLine("Number of bytes needed by a PointA object: {0}",
          Marshal.SizeOf(typeof(PointA)));
        Console.ReadKey();
    }
    public struct PointA
    {
        public int x;
        public string posorneg;
        public bool isvalid;
    }
    public struct PointB
    {
        public bool isvalid;
        public int x;
        public string posorneg;
    }
}

I got as result:

Number of bytes needed by a PointB object: 16
Number of bytes needed by a PointA object: 24

我不明白这个结果,我需要知道:

  1. 结构的属性顺序是否会干扰分配的字节数?
  2. 如果是这样,为什么?减少分配结构所需的字节数的最佳实践是什么?

马歇尔.c#应用程序中的sizeof和structure

您在64位模式下运行此代码,对象引用占用8字节。StructLayout的默认值。Pack为8,与大多数C编译器的默认设置相匹配。它确保结构体的成员与成员大小的倍数的地址对齐。一个重要的规则,使代码快速,并保持更新的变量原子。它避免了处理器必须使用多个内存总线周期来访问变量值。

注释每个成员存储在为结构体分配的内存中的位置:

    public struct PointA
    {
        public int x;             // Offset 0, 4 bytes
                                  // Offset 4, 4 bytes of padding
        public string posorneg;   // Offset 8, 8 bytes
        public bool isvalid;      // Offset 16, 4 bytes
                                  // Offset 20, 4 bytes of padding
    }                             // Total: 24 bytes
    public struct PointB
    {
        public bool isvalid;      // Offset 0, 4 bytes
        public int x;             // Offset 4, 4 bytes
        public string posorneg;   // Offset 8, 8 bytes
    }                             // Total: 16 bytes

需要插入前4个字节的填充,以保持字符串引用成员与8对齐。当您将结构体存储在数组中时,最后4个字节的填充需要确保字符串仍然对齐。

PointB中完全不需要填充,所有内容都正确排列。您可以很容易地看到Pack属性的效果,将[StructLayout(LayoutKind.Sequential, Pack = 4)]应用于结构体,您将看到它们现在都占用16字节。当然,实际上不可能对字段重新排序或修补打包,您需要匹配本机代码使用的结构体的布局。

值得注意的是CLR自动执行这种布局优化。在应用了[StructLayout(LayoutKind.Auto)]的类或结构体上,它重新排序字段以获得最佳布局。托管代码的优点之一,使其与本机代码竞争。请记住,您从Marshal类中看到的内容仅在被封送的类或结构之后应用。内部布局是无法发现的,这就是CLR可以玩这些优化技巧的原因。