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

时间:2012-09-24 20:47:03

标签: c# struct size marshalling guid

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

struct S1
{
  Guid id;
}

struct S2 
{
  Guid id;
  short s;
}

struct S3 
{
  Guid id;
  short s;
  short t;
}

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

Size:
S1 = 16, as expected.
S2 = 20, copied an instance to a byte array, it only occupies first 18 bytes.
S3 = 20.

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

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

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

非常感谢!

3 个答案:

答案 0 :(得分:9)

这是因为附加到结构的隐含[StructLayout],字段是重要的字段。它规定了在编组之后结构的成员是如何对齐的。 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;
}

输出:8

a成员强制增加大小,向结构添加两个额外的填充字节,以确保在数组中使用结构时,int仍然与一个4的倍数偏移对齐。您可以通过应用属性来更改结果:

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

输出:6

当在数组中使用结构时,a成员现在将被错误对齐。

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

有关结构的更多背景知识以及在this answer中使用.NET处理它们的特殊方式。

答案 1 :(得分:0)

我没有看到你在结构定义上使用StructLayoutAttribute。因此,你不会知道它们是如何“布局”的。你怎么知道他们有顺序布局?

有些来源:sizeof() structures not known. Why?When should I explicitly specify a StructLayout?

答案 2 :(得分:0)

我相信这是因为有些项目必须在内存中与4字节(或8字节)边界对齐。因此,struct是这个大小的倍数,因此结构的数组都将正确对齐。在包含字符串的64位机器上强制它是8字节的倍数;即使在64位上,GUID似乎也只需要4个字节的倍数。 如果包含GUID的结构不是4字节大小的倍数,则某些GUID将不在这些结构的数组中的4字节边界上。 我不认为你可以避免'问题' - 为什么这是一个问题?