StructLayoutAttribute.Pack混淆

时间:2017-12-25 15:08:56

标签: c#

我在解释两段代码的结果时遇到了一些问题。

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 0)]
struct MyStruct
{
    public byte b1;
    public char c2;
    public int i3;
}

public class Example
{
    public unsafe static void Main()
    {
        MyStruct myStruct = new MyStruct();
        byte* addr = (byte*)&myStruct;    
        Console.WriteLine("Size:      {0}", sizeof(MyStruct));    
        Console.WriteLine("b1 Offset: {0}", &myStruct.b1 - addr);
        Console.WriteLine("c2 Offset: {0}", (byte*)&myStruct.c2 - addr);
        Console.WriteLine("i3 Offset: {0}", (byte*)&myStruct.i3 - addr);    
        Console.ReadLine();
    }
}

以上结果是

Size :      8

b1 Offset:  0
c2 Offset:  2
i3 Offset:  4

如果我发表评论public char c2;Console.WriteLine("c2 Offset: {0}", (byte*)&myStruct.c2 - addr);,我会得到

Size :      8

b1 Offset:  0
i3 Offset:  4

现在我想我可以解释第二种情况,其中默认打包大小是当Pack = 0时myStruct的最大元素大小的大小。因此它是1字节+ 3字节的填充+ 4字节= 8。 / p>

但同样的情况似乎并不适用于第一种情况。我的预期结果是(1个字节+ 3个字节的填充)+(2个字节用于char + 2个字节的填充)+(4个字节用于int)。所以总大小应为12,因为打包大小为4字节(int的大小),相应的偏移量为0,4,8。

我在这里缺少什么?

由于

1 个答案:

答案 0 :(得分:1)

要理解对齐,考虑以X字节块(其中X是您的类型对齐)读取结构的内容可能会有所帮助。在你的例子中,X是4.如果没有添加填充,读取第一个结构的前4个字节(带有char)将读取byte,char,然后读取下一个int字段的一个字节。这(避免读取部分字段字节)是需要填充的原因。要“修复”问题 - 需要填充一个字节。然后,第一个4字节读取将读取字节和字段(以及填充的一个字节),接下来的4字节读取将读取整数字段。按预期添加填充是浪费的,因为您可以通过较小的总大小(超过预期的12个字节)实现相同的目标。