C# 記憶體對齊

ProjectDD發表於2024-10-06
[StructLayout(LayoutKind.Sequential)]
unsafe struct B{
// public int field1;
public double field2;
public string field3;
byte* field4;
byte field5;
nint field6;
byte field7;
byte field8;
short field9;
short field10;
short field11;
// decimal field7;
}
sizeof(B)=48 ;
和LayoutKind.Auto的結果一樣的, 反覆試了幾遍感覺似乎和欄位的順序沒關係,開啟field1 的話,它還是會和別的不足一個pack的欄位接合。。 除非出現轉彎
那麼我來名詞解釋下,pack 就是說記憶體地址的長度,64位=8位元組在這樣的記憶體平臺上 pack=address length=8 byte , 在32位記憶體平臺上,是4 byte , C#記憶體對齊的規則 大致是這樣的,從office 0開始往後依次排,按address len來計算,只要多個欄位的長度相加沒出現“轉彎” 或 稱為“摺疊”那麼這種 多個欄位放入一個 address len(pack)之內的情況就是會發生的,應該是自動發生的,比方一個 byte 型別是 1,一個short 是2,一個 int是4 這些欄位都小於 memory address len 所以多個這樣的欄位可以放入一個 pack裡,並且這是自動的,但是若 一個Int + double這就不行,因為4+8 =12 已經大於一個pack =8了,所以出同現疊這就不允許 (這個規則 是我猜測的,是符合邏輯的推測)因為若出現各種摺疊則 讓欄位的讀取和識別將變得異常複雜 和困難
[StructLayout(LayoutKind.Sequential)]
struct C1{
  int filed1;
  double field2;
  short field3;
}
[StructLayout(LayoutKind.Auto)]
struct C2{
  int filed1;
  double field2;
  short field3;
}
[StructLayout(LayoutKind.Sequential)]
struct C3{
  int filed1;
  short field3;
  double field2;
}
[StructLayout(LayoutKind.Auto)]
struct C4{
  int filed1;
  short field3;
  double field2;
}

unsafe{
  Console.WriteLine("Sequential,C1:int,double,short sizeof:{0}",sizeof(C1));
  Console.WriteLine("Auto,C2:int,double,short sizeof:{0}",sizeof(C2));
  Console.WriteLine("Sequential,C3:int,short,double sizeof:{0}",sizeof(C3));
  Console.WriteLine("Auto,C4:int,short,double sizeof:{0}",sizeof(C4));
}

Sequential,C1:int,double,short sizeof:24
Auto,C2:int,double,short sizeof:16
Sequential,C3:int,short,double sizeof:16
Auto,C4:int,short,double sizeof:16

using System.Runtime.InteropServices;
unsafe struct A{
  public int field1;
  public double field2;
  public string field3;
  public int Field1 { get => field1; set => field1 = value; }
  public double Field2 { get => field2; set => field2 = value; }
  public void M1() => Console.WriteLine("M1");
}
[StructLayout(LayoutKind.Sequential)]    
unsafe struct B{
  public int field1;
  public double field2;
  public string field3;
  byte* field4;
  byte field5;
  nint field6;
  byte field7;
  byte field8;
  short field9;
  short field10;
  short field11;
  // decimal field7;
}
[StructLayout(LayoutKind.Auto)]    
unsafe struct B2{
  public int field1;
  public double field2;
  public string field3;
  byte* field4;
  byte field5;
  nint field6;
  byte field7;
  byte field8;
  short field9;
  short field10;
  short field11;
  // decimal field7;
}

unsafe{
  var x1=new A();
  var p1 = &x1;
  p1->Field1=10;
  Console.WriteLine(x1.Field1);
  p1->M1();
  Console.WriteLine(sizeof(A));
  Console.WriteLine(sizeof(B));
  Console.WriteLine(sizeof(B2));
}

10
M1
24
48
48

為什麼 sizeof(B) 和sizeof(B2) 都為48 沒搞懂,不應該說 sizeof(B) = 56嗎? 誰能解釋

相關文章