2010-03-11 111 views
9

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

我在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個字節。

當我在該結構中的C++一個sizeof()

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

調試控制檯顯示:

一下SizeOf(網格點)= 24

但我預期具有20個字節。爲什麼我看到差異?

+0

在這裏看到:http://www.vsj.co.uk/articles/display.asp?id=501 – 2010-03-11 20:02:06

回答

7

實際上,從技術上講,結構必須是20字節的最小的。如果您在發送時分配更多,接收器將不會使用/複製它們。問題始終未解決。

這就是說,我看到了問題。嗯。我認爲這個問題是最後一個長期的問題......恕我直言對齊到八個字節,之前注入四個空字節。我認爲有一個八字節元素沒有對齊八字節邊界會有性能損失。

附加StructLayout屬性以手動確定每個元素的偏移量。那麼你應該能夠把事情排好隊。

參考:How to control the physical layout of the data fields in the .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 
} 

即至少應對準元件,以一個字節的邊界。如果需要,您可以進一步定義每個元素的確切開始。

+0

您的解決方案也適用。非常感謝你。你的解決方案似乎比約翰的答案容易。我會用你的解決方案.. Bye – user291830 2010-03-11 20:22:41

2

嘗試添加屬性[StructLayout(LayoutKind.Sequential,Pack = 1)]並查看會發生什麼。我懷疑是8字節填充,所以它是3x8字節。

+1

沒有,對象.NET(除了如int原語)有尺寸比的總和還多領域。 – Andrey 2010-03-11 20:01:10

9

作爲一般規則,CPU喜歡將內存中的變量與其大小的偶數倍對齊,因此四字節整數應位於可被四整除的內存地址上,並且八字節long應位於可被8整除的地址處。

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 
} 

您可以通過長期的第一個值修正這個問題,作爲一項規則,如果你總是把最大的價值在你的結構開始,你贏了沒有插入任何填充以保持成員對齊。

您還可以通過結構聲明之前加入

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

解決它,但是這將導致未對齊的long time這會降低性能。在某些CPU上,它會使性能受到很大影響。 (例如,​​會因錯位會員而發生錯誤)。 x86 CPU只有輕微的性能損失,但未來的CPU有可能會導致性能下降,所以最好設計好結構以便正確對齊(而不是打包)。

+0

你有完整的權利!非常感謝 – user291830 2010-03-11 20:08:34

+1

哇,我喜歡這種類型的反饋。我剛剛學到了一些新鮮有趣的東西。 – 2010-03-11 20:39:54

1

TomTom很好地回答了這個問題,我認爲,但如果最終出現在棘手的COM互操作結構中,還有另一種方法。每個字段可以使用FieldOffset屬性自行對齊。

[StructLayout(LayoutKind.Explicit)] 
public struct COMPoint 
{ 
    [FieldOffset(0)] public int X; 
    [FieldOffset(4)] public int Y; 
}