我在解释两段代码的结果时遇到了一些问题。
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。
我在这里缺少什么?
由于
答案 0 :(得分:1)
要理解对齐,考虑以X字节块(其中X是您的类型对齐)读取结构的内容可能会有所帮助。在你的例子中,X是4.如果没有添加填充,读取第一个结构的前4个字节(带有char)将读取byte,char,然后读取下一个int字段的一个字节。这(避免读取部分字段字节)是需要填充的原因。要“修复”问题 - 需要填充一个字节。然后,第一个4字节读取将读取字节和字段(以及填充的一个字节),接下来的4字节读取将读取整数字段。按预期添加填充是浪费的,因为您可以通过较小的总大小(超过预期的12个字节)实现相同的目标。