public struct TestStruct
{
public int first;
public int second;
public int third;
}
Marshal.SizeOf返回12,这是我假设的,因为整数是4个字节。如果我要将第三个改为double而不是int,我会期望Marshal.SizeOf返回16.确实如此。但是如果我要添加一个双倍的第四个,Marshal.SizeOf返回24,当我期望20.我可以有10个整数并且最终每个int计为每个4字节。但是如果我在3个整数后添加一个双精度数,那么这个尺寸就不是我所期望的。
public struct TestStruct //SizeOf 12
{
public int first;
public int second;
public int third;
}
public struct TestStruct //SizeOf 16
{
public int first;
public int second;
public double third;
}
public struct TestStruct //SizeOf 24, but I feel like it should be 20
{
public int first;
public int second;
public double third;
public int fourth;
}
我的想法让我误入歧途?
答案 0 :(得分:8)
除了JimR的答案,您还可以使用StructLayout属性显式更改此行为:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TestStruct // sizeof is now 20
{
public int first;
public int second;
public double third;
public int fourth;
}
您告诉编译器这个结构是按顺序排列的,并且打包类型应该是1,这意味着所有字段都是直接相继布局的。 Pack 0(默认值)告诉编译器使用当前平台填充...而其他任何东西(以2的倍数表示)将在那些特定边界中进行布局。我会建议不要这样做......根据你的使用情况,它可能变得无法预测。
有关详细信息,请参阅此MSDN文章:http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.pack.aspx
答案 1 :(得分:5)
你没有考虑在结构中添加任何填充。
在某些情况下,CPU更有效地读取多个大小的内容。例如,一些像int这样的CPU在4字节边界上对齐。如果int未对齐,某些CPU必须发出2次读取。
当英特尔处理器上的SSE类型指令触及时,int,float和double对对齐特别敏感。
答案 2 :(得分:4)
我认为答案在于数据字段的对齐。
例如,默认情况下,使用C#定义的结构将具有此属性:
[StructLayout(LayoutKind.Sequential)]
如果你看一下LayoutKind.Sequential的定义,它会说:
对象的成员按顺序排列,按导出到非托管内存时的显示顺序排列。成员根据StructLayoutAttribute.Pack中指定的包装进行布局,并且可以是不连续的。
如果您要指定此属性:
[StructLayout(LayoutKind.Auto)]
你会得到你期望的尺寸--20。