Marshal.SizeOf在包含guid的结构上提供了额外的字节

use*_*516 11 c# size struct guid marshalling

我有几个具有顺序布局的结构:

struct S1
{
  Guid id;
}

struct S2 
{
  Guid id;
  short s;
}

struct S3 
{
  Guid id;
  short s;
  short t;
}
Run Code Online (Sandbox Code Playgroud)

调用Marshal.SizeOf上面的结构类型,我得到了:

Size:
S1 = 16, as expected.
S2 = 20, copied an instance to a byte array, it only occupies first 18 bytes.
S3 = 20.
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么S2的大小是20而不是18.而这个问题只出现Guid在结构中.

抱歉找不到msdn的任何有用信息.我知道Marshal.SizeOf类型将在内存中占用的空间大小,但我想知道为什么它需要2个额外的字节来使大小为4的倍数.

我怎样才能避免这个"问题"?

非常感谢!

Han*_*ant 10

这是因为附加到结构的隐含[StructLayout],Pack字段是重要的.它规定了在编组之后结构的成员是如何对齐的.Pack的默认值是8.这表示任何小于或等于8字节的成员都是对齐的.换句话说,short将与偏移量对齐,偏移量为2的倍数,int为4,long为double或double为8.

关键点是,在创建结构数组时,对齐应该仍然有效.使用更简单的示例更容易演示:

using System;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        Console.WriteLine(Marshal.SizeOf(typeof(Example)));
        Console.ReadLine();
    }
}
struct Example {
    public int a;
    public short b;
}
Run Code Online (Sandbox Code Playgroud)

输出:8

所述a构件强制增大的尺寸,两个额外的填充字节添加到该结构以确保INT仍然对准到偏移这是4的倍数时,该结构被在阵列中使用.您可以通过应用属性来更改结果:

[StructLayout(LayoutKind.Sequential, Pack = 2)]
struct Example {
    public int a;
    public short b;
}
Run Code Online (Sandbox Code Playgroud)

产量:6

a当该结构在一个阵列被用于构件现在将未对齐的.

回到Guid,您无法从声明中看到它,但它内部由许多成员组成.第一个是私有字段命名_a,它是一个int.因此,Guid需要4字节对齐.因此,当在数组中使用它时,需要2个额外的填充字节才能使结构正确对齐.在S2上你需要Pack = 1或Pack = 2来获得18个字节.

关于结构的更多背景以及在这个答案中用.NET处理它们的特殊方式.