当我有一个双倍的时候,为什么我的结构会出现意想不到的大小?

时间:2012-08-23 03:11:50

标签: c# struct double

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;
}

我的想法让我误入歧途?

3 个答案:

答案 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的定义,它会说:

LayoutKind Enumeration

  

对象的成员按顺序排列,按导出到非托管内存时的显示顺序排列。成员根据StructLayoutAttribute.Pack中指定的包装进行布局,并且可以是不连续的。

如果您要指定此属性:

[StructLayout(LayoutKind.Auto)]

你会得到你期望的尺寸--20。