本來打算寫一篇文章,詳細地討論一下結構的記憶體布局,但是想了下,跟路西菲爾的這篇文章也差不多,所以這裡只做一下補充:
一、對齊長度
如果沒有顯式的指定對齊長度,將以結構中佔用空間最大的成員的長度作為對齊長度;如果要顯式指定對齊長度,需設定StructLayoutAttribute.Pack,如:
[StructLayout(LayoutKind.Sequential,Pack=4)]
struct MyStruct
{
}
對齊長度的作用在於:如果某個欄位的長度大於或等於對齊長度,則對齊長度沒用;如果小於對齊長度,則以對齊長度為單元,佔用的空間是對齊長度的整數倍,同時保證不大於對齊長度的欄位一定分配在同一單元,並且其首地址一定是欄位長度的整數倍。
如:
struct MyStruct
{
byte a;
char b;
int c;
}
第0個位元組為a,第1個位元組無資料,第2,3個位元組為b,第4,5,6,7為c。
二、“詭異”的decimal類型
有這樣一個結構,請問其佔用空間是多少?
struct MyStruct
{
int a;
deciaml b;
double c;
}
最初我以為是48個位元組,因為int是4個位元組,decimal是16個位元組,double是8個位元組,decimal最大,所以以16個位元組對齊,所以是48個位元組。
但實際上是32個位元組。
這其中的原因在於,decimal是由4個int構成的:
struct Decimal
{
private int flags;
private int hi;
private int lo;
private int mid;
.....//其他不佔據對象記憶體的成員
}
所以上述結構中占記憶體最大的成員是double,對齊長度是8
三、.Net中實現C語言的Union
可以通過下面的自訂欄位位置的方法,在.Net中實現C風格的Union
[StructLayout(LayoutKind.Explicit)]
struct MyStruct
{
[FieldOffset(0)]
int a;
[FieldOffset(2)]
short b;
[FieldOffset(3)]
byte c;
}
從0開始計數,第2個位元組為a,b共用,第3個位元組為a,b,c共用。