我有几个具有顺序布局的结构:
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的倍数。
我怎样才能避免这个“问题”?
非常感谢!
答案 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字节边界上。 我不认为你可以避免'问题' - 为什么这是一个问题?