C# Marshal.Sizeof()返回意外值

C# Marshal.Sizeof()返回意外值,c#,c++,marshalling,structlayout,C#,C++,Marshalling,Structlayout,我正在调试由第三方编写的C语言代码。该项目是一个旧的C++项目,它由承包商在C.*中改写,我无法访问承包商。我编写了原始的C++版本。 问题在于,当C#代码获取表示通过UDP连接接收的数据的结构的大小时 结构定义为: [StructLayout(LayoutKind.Sequential,Pack=1)] internal class PROXY_HDR { public ushort pad; public ushort label; public char flags

我正在调试由第三方编写的C语言代码。该项目是一个旧的C++项目,它由承包商在C.*中改写,我无法访问承包商。我编写了原始的C++版本。 问题在于,当C#代码获取表示通过UDP连接接收的数据的结构的大小时

结构定义为:

[StructLayout(LayoutKind.Sequential,Pack=1)]
internal class PROXY_HDR {
    public ushort pad;
    public ushort label;
    public char flags;
    public ushort length;
    public char[] ip = new char[4];
    public ushort port;
}
此结构的大小检索为:

int size = Marshal.Sizeof(typeof(PROXY_HDR));
返回的值是17,而不是预期的13。对于4字节的差异,我怀疑ip成员,但这只是因为它的表达方式不同于其他成员(使用“new”),但我没有其他依据来决定

我通常不会在解析接收到的数据包的C#代码中使用这种封送处理,因此我不知道如何修改此结构定义,使其与原始版本大小“对齐”

我可以用

int size = 13;
但那是作弊,对吗


我是否可以修改此布局以获得正确的大小?

将此添加到结构中:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal class PROXY_HDR
{
    public ushort pad;
    public ushort label;
    public byte flags;
    public ushort length;
    [MarshalAs(UnmanagedType.ByValArray,
        SizeConst = 4, ArraySubType = UnmanagedType.U1)]
    public byte[] ip;
    public ushort port;
}

这将告诉编译器将其视为典型的C样式数组,而不是指针。这应该是字节,因为IP地址是无符号字符数组
char
通常不用于这些类型的头,它通常是
byte
(即:
unsigned char

我没有实际的答案,但是你可以像我在回答一个不相关的问题时那样尝试显式地设置字段偏移量。为什么你希望它是13?@IanKemp,因为对于x86(32位),它确实返回13,如果编译为x64,则返回+4…@AlexeiLevenkov——如果你正确地封送它,它返回64位和32位以下的13个字节bit@Andy事实上,也没有问题可以问:)显然,没有人每天不做这些事情,就不会期望
char
的sizeof=1。。。OP不知道引用类型。。。“有很多事情要解释。”芭丝谢芭——我想这是对的。。我的解释表明,我不是100%确定为什么它是正确的。我必须对此进行研究,并提出更好的解释。@Andy:是的,这很有效。至于“char”定义,我认为C开发人员试图尽可能忠实于原始的C++代码,并且这个特定的结构从未被更新为使用“字节”,就像大多数其他的。非常感谢。请注意,最初的问题只是因为将
ip
视为指针(32位或64位,取决于编译代码的方式)。显然,
char
是默认编组的单字节-我没有要确认的链接,但您可以很容易地自己尝试(直接使用size=13或17查看,这只能用char=1的大小来解释).@user3235770——请注意,您可以通过向属性添加
ArraySubType=UnmanagedType.U1
或其他任何内容使其更具体。我不知道这是否有帮助。事实上,我只是注意到我只添加了MarshalAs行,而不是在后面的行中从CHAR到BYTE的更改。所以很明显,这是作为一个指针的解释。