2010-03-11 58 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; 
}