马歇尔.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
我不明白这个结果,我需要知道:
- 结构的属性顺序是否会干扰分配的字节数?
- 如果是这样,为什么?减少分配结构所需的字节数的最佳实践是什么?
您在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可以玩这些优化技巧的原因。