C# 查找类型对象的大小?
我定义这个结构C# 查找类型对象的大小?,c#,C#,我定义这个结构 public enum E1 : byte { A, B, C } public enum E2 : byte { D, E, F } [StructLayout(LayoutKind.Sequential, Pack=4)] public struct SomeStruct { public Int32 _var1; //4 byte public E1 _var2; //1 byte(because
public enum E1 : byte
{
A,
B,
C
}
public enum E2 : byte
{
D,
E,
F
}
[StructLayout(LayoutKind.Sequential, Pack=4)]
public struct SomeStruct
{
public Int32 _var1; //4 byte
public E1 _var2; //1 byte(because Pack is 4 this will take 4 byte)
public E2 _var3; //1 byte(because Pack is 4 this will take 4 byte)
public UInt64 _var4; //8 byte
}
现在,由于我添加了Pack=4的StructLayout属性,我希望我定义的每个变量都将保持数据字段的对齐为4
所以我希望
int val = Marshal.SizeOf( typeof( SomeStruct ) );
但是我检查了密码,发现val是16
那么它是怎样的呢?我的误解在哪里
SizeOf
以字节指定大小
现在,如果我们计算一下,我们会发现:
具有Int32
位,因此32
字节4
具有Int64
位,因此64
字节8
- 两个
s都编码在一个字节上,因此enum
byte1
1+1+4+8
,因此14
字节
但是:大多数系统不喜欢使用字节:它们使用字(16位)或dwords(32位)获取和存储数据。由于最小化数据结构会导致截断数据并重新插入数据的操作,因此它充满了尾随零
如果您在这样的系统上工作,编译器可能希望将数据打包成16位(或更高位)的块。这些更容易:例如,如果您想访问数组中的一个元素,它不必将两个单词提取到内存中,因为结构是在单词之间拆分的
演示数据如何打包的实验:
using System.Runtime.InteropServices;
namespace Foo {
public enum E1 : byte
{
A,
B,
C
}
public enum E2 : byte
{
D,
E,
F
}
[StructLayout(LayoutKind.Sequential,Pack=4)]
public struct SomeStruct
{
public int _var1; //4 byte
public byte _var2; //1 byte(because Pack is 4 this will take 4 byte)
public byte _var3; //1 byte(because Pack is 4 this will take 4 byte)
public ulong _var4; //8 byte
public SomeStruct (int var1, byte var2, byte var3, ulong var4) {
this._var1 = var1;
this._var2 = var2;
this._var3 = var3;
this._var4 = var4;
}
}
}
Foo.SomeStruct i = new Foo.SomeStruct(1302,5,17,1425);
Marshal.SizeOf( typeof( Foo.SomeStruct ) );
sizeof(Foo.SomeStruct);
int size = sizeof(Foo.SomeStruct);
byte[] result = new byte[size];
IntPtr buffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(i, buffer, false);
Marshal.Copy(buffer, result, 0, size);
结果:
{ 22, 5, 0, 0, 5, 17, 0, 0, 145, 5, 0, 0, 0, 0, 0, 0 }
因此,结构被编码为:
0 32 40 48 64 128
+----------------+----+----+--------+--------------------------------+
| _var1 | _v2| _v3| ------ | _var4 |
+----------------+----+----+--------+--------------------------------+
如果使用int
/uint
对变量进行编码,则会得到:
{ 22, 5, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 5, 0, 0, 0, 0, 0, 0 }
或:
4+1+1+8=14
withPack=4
它是16
@yansof:从uint
导出enum
s。文档似乎对Pack
值有不同的解释:这意味着每个字段都从偏移量n*2
开始,其中n
是基于0的元素计数。例如:使用Pack=2
,字段1从偏移量0开始,字段2从偏移量2开始,字段3从偏移量4开始,等等。基本上:每个字段都被填充。但是,您的答案表明,所有字段都分组在一起,然后在末尾填充。我误解了什么?@Jeroenvanevel:根据一些实验,似乎——至少是Mono编译器——忽略了packing属性。
0 32 64 96 128 192
+--------+--------+--------+--------+----------------+
| _var1 | _var2 | _var3 | ------ | _var4 |
+--------+--------+--------+--------+----------------+