Dot-Net

.NET 中結構的大小

  • January 15, 2013

我的問題是將 C 中的程序之間的結構發送到 C# 程序。

我在 C# 中創建了一個結構:

public struct NetPoint {
   public float lat; // 4 bytes
   public float lon; // 4 bytes
   public int alt; // 4 bytes
   public long time; // 8 bytes
}

結構的總大小必須為 20 字節。

當我sizeof()在 C++ 中做這個結構時,

System.Diagnostics.Debug.WriteLine(
   "SizeOf(NetPoint) = " +
   System.Runtime.InteropServices.Marshal.SizeOf(new NetPoint()));

調試控制台顯示:

SizeOf(NetPoint) = 24

但我預計會有 20 個字節。為什麼我看到了不同?

實際上,從技術上講,該結構必須至少為 20 個字節。如果您在發送時分配更多,接收者就不會使用/複製它們。問題總是分配不足。

也就是說,我看到了問題。唔。我認為問題是最後一個長……恕我直言,它與八個字節對齊,之前註入了四個空字節。我認為八字節元素未與八字節邊界對齊會降低性能。

附加StructLayout屬性以手動確定每個元素的偏移量。然後,您應該能夠使事情井井有條。

參考:.NET Framework 2.0中如何控制數據域的物理佈局

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct NetPoint {  
   public float lat; // 4 bytes 
   public float lon; // 4 bytes 
   public int alt; // 4 bytes 
   public long time; // 8 bytes 
} 

至少應該將元素對齊到一個字節的邊界。如果需要,您也可以通過定義每個元素的確切開始來更進一步。

作為一般規則,CPU 喜歡將變數在記憶體中對齊的位置是其大小的偶數倍,因此 4 字節整數應位於可被 4 整除的記憶體地址上,而 8 字節整數應位於可被 4 整除的記憶體地址上long。在一個能被八整除的地址。

C#(和 C++)語言設計者知道這一點,他們會在結構中插入填充以提供必要的對齊。所以你的結構的實際佈局如下所示:

public struct NetPoint {
   public float lat;          // 4 bytes   Offset  0
   public float lon;          // 4 bytes   Offset  4
   public int alt;            // 4 bytes   Offset  8
   int to_preserve_alignment; // 4 bytes   Offset 12
   public long time;          // 8 bytes   Offset 16
}

您可以通過將 long 作為第一個值來解決此問題,通常,如果您始終將最大值放在結構的開頭,則不會插入任何填充以保持成員的對齊。

您也可以通過添加來修復它

[StructLayout(LayoutKind.Sequential, Pack = 4)]

在結構聲明之前,但這會導致錯位,long time從而損害性能。在某些 CPU 上,它會嚴重影響性能。(例如,ALPHA AXP會在未對齊的成員上出錯)。x86 CPU 只有輕微的性能損失,但未來的 CPU 可能會面臨嚴重的性能損失,因此如果可以的話,最好將結構設計為正確對齊(而不是打包)。

引用自:https://stackoverflow.com/questions/2428168