5
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,最终每个 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;
}

我的想法让我误入歧途了吗?

4

3 回答 3

9

除了 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

于 2012-08-23T03:40:42.587 回答
6

您没有考虑放入结构中的任何填充。

在某些情况下,CPU 读取其大小的倍数会更有效。例如,一些 CPU 喜欢在 4 字节边界上对齐的整数。如果 int 未对齐,某些 CPU 必须发出 2 次读取。

当 int、float 和 double 可能被英特尔处理器上的 SSE 类型指令触及时,它们对对齐特别敏感。

于 2012-08-23T03:33:46.863 回答
4

我相信答案在于数据字段的对齐。

例如,默认情况下,使用 C# 定义的结构将具有此属性:

[StructLayout(LayoutKind.Sequential)]

如果您查看 LayoutKind.Sequential 的定义,它会指出:

布局种类枚举

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

如果您要指定此属性:

[StructLayout(LayoutKind.Auto)]

你会得到你期望的大小 - 20。

于 2012-08-23T03:41:21.177 回答