.net NET中结构的大小

.net NET中结构的大小,.net,interop,struct,.net,Interop,Struct,我的问题是在C语言的程序和C语言的程序之间发送一个结构 我用C#做了一个结构: 结构的总大小必须为20字节 当我在C++结构中做 siZoF()/Cuff>时, System.Diagnostics.Debug.WriteLine( "SizeOf(NetPoint) = " + System.Runtime.InteropServices.Marshal.SizeOf(new NetPoint())); 调试控制台显示: SizeOf(网点)=24 但我希望有20个字节。为什

我的问题是在C语言的程序和C语言的程序之间发送一个结构

我用C#做了一个结构:

结构的总大小必须为20字节

当我在C++结构中做<代码> siZoF()/Cuff>时,

System.Diagnostics.Debug.WriteLine(
    "SizeOf(NetPoint) = " +
    System.Runtime.InteropServices.Marshal.SizeOf(new NetPoint()));
调试控制台显示:

SizeOf(网点)=24


但我希望有20个字节。为什么我会看到差异?

尝试添加属性[StructLayout(LayoutKind.Sequential,Pack=1)],看看会发生什么。我怀疑是8字节的填充,所以它是3x8字节。

实际上,从技术上讲,结构必须是最小的20字节。如果你在发送时分配更多,接收者就不会使用/复制它们。问题总是分配不足

也就是说,我看到了问题所在。嗯。我想问题是最后一段时间。。。。其中IMHO与8个字节对齐,在之前注入4个空字节。我认为八字节元素与八字节边界不对齐会导致性能下降

附加属性以手动确定每个元素的偏移量。然后你应该能够把事情安排好

参考:


至少应该将元素与一个字节的边界对齐。如果需要,您还可以进一步定义每个元素的确切起始位置。

作为一般规则,CPU喜欢将变量在内存中的某个位置对齐,该位置是其大小的偶数倍,因此四字节整数应该位于可被四整除的内存地址上,一个8字节的
应该位于一个可以被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
}
您可以通过将long作为第一个值来解决此问题,通常,如果总是在结构的开头放置最大值,则不会插入任何填充以保持成员对齐

您还可以通过添加

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

在结构声明之前,但这将导致错误对齐
很长时间
,从而影响性能。在某些CPU上,这会严重影响性能。(例如,这将导致未对齐的构件出现故障)。CPU只有轻微的性能损失,但未来的CPU可能会有严重的性能损失,因此,如果可以的话,最好将您的结构设计为正确对齐(而不是打包)。

TomTom很好地回答了这个问题,我想,但如果您最终遇到棘手的COM互操作结构情况,还有另一种选择。可以使用FieldOffset属性单独对齐每个字段

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

不,在.net中的对象(除了像int这样的原语)的大小大于字段的总和。请看这里:您的解决方案也可以。非常感谢你。你的答案似乎比约翰的答案更容易。我将使用你的解决方案。。拜,我喜欢这种反馈。我刚刚学到了一些新的有趣的东西。
[StructLayout(LayoutKind.Sequential, Pack = 4)]
[StructLayout(LayoutKind.Explicit)]
public struct COMPoint
{
    [FieldOffset(0)] public int X;
    [FieldOffset(4)] public int Y;
}