为什么在创建后清除此结构?

时间:2009-08-24 19:32:28

标签: c# struct

我有一个看起来像这样的结构:

[StructLayout(LayoutKind.Sequential)]
public struct in_addr {
    public Anonymous1 S_un;

    [StructLayoutAttribute(LayoutKind.Explicit)]
    public struct Anonymous1 {
        [FieldOffsetAttribute(0)]
        public Anonymous2 S_un_b;

        [FieldOffsetAttribute(0)]
        public Anonymous3 S_un_w;

        [FieldOffsetAttribute(0)]
        public uint S_addr;
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct Anonymous2 {
        public byte s_b1;
        public byte s_b2;
        public byte s_b3;
        public byte s_b4;
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct Anonymous3 {
        public ushort s_w1;
        public ushort s_w2;
    }

    public in_addr(byte[] address) {
        S_un.S_addr = (uint)BitConverter.ToInt32(address, 0);

        S_un.S_un_b.s_b1 = address[0];
        S_un.S_un_b.s_b2 = address[1];
        S_un.S_un_b.s_b3 = address[2];
        S_un.S_un_b.s_b4 = address[3];

        S_un.S_un_w.s_w1 = 0;
        S_un.S_un_w.s_w2 = 0;
    }
}

当我尝试创建此结构的新实例时,每个字节字段都设置为0。

in_addr temp = new in_addr(bytes);

我已经逐步完成了struct的构造函数,并验证了字节确实被分配给了字段。但是当我走出构造函数并检查temp的值时,一切都是0。

造成这种情况的原因是什么?

5 个答案:

答案 0 :(得分:5)

由于这些原因:

S_un.S_un_w.s_w1 = 0;
S_un.S_un_w.s_w2 = 0;

它们通过

映射到您的4个字节
[FieldOffsetAttribute(0)]
public Anonymous2 S_un_b;

[FieldOffsetAttribute(0)]
public Anonymous3 S_un_w;

答案 1 :(得分:3)

我无法重现这一点;你的代码适合我。我正在使用Mono,但我非常怀疑这是Microsoft C#编译器中的一个错误,你更有可能在其他地方出错。

答案 2 :(得分:1)

我刚刚使用C#在VisualStudio 2008中对此进行了测试,得到了预期的输出(1,2)。

尝试发布您遇到问题的实际示例代码。

编辑这就是为什么示例代码可能不好;)

您的问题出在StructLayout.Explicit Anonymous1上。是否有特殊原因

  1. 你做了明确的而不是顺序的,并按照你想要的顺序排列
  2. 你把所有的索引都留为0
  3. 当我将其更改为Sequential并删除属性时,它对我来说很好。

    编辑2 (已删除)

    编辑3

    您的问题在于构造函数中的赋值。不知道我是怎么错过这个的。您不需要设置所有这些变量,因为您的FieldOffset属性会将它们全部存储在同一位置。结构本身只占用4个字节的内存(理论上,无论如何)。无论您是通过intbyte还是两个short访问它们,它们都会转到同一个地方。因此,前两组分配(intbyte)是冗余的,最后一组(short将它们设置为0)清除你刚刚做了什么。

    不幸的是C#编译器不知道这一点,所以我确定你添加了最后一个赋值,因为它抱怨结构没有完全分配。首先为shortint添加虚拟分配,然后从数组中明确指定byte

答案 3 :(得分:0)

如果您使用的是C#3.0,请尝试以下操作:

MyStruct ms = new MyStruct
{
    MyByte = 1,
    MyNestedStruct.NestedStryctByte = 2
}

这应该有效,并且可以减轻在结构中使用构造函数的需要。如果无法直接初始化NestedStructByte,请先创建它:

MyStruct ms = new MyStruct
{
    MyByte = 1,
    MyNestedStruct = new MyStruct.NestedStruct
    {
        NestedStryctByte = 2
    }
}

答案 4 :(得分:0)

我测试了你的代码 - 一切都很好。

public struct MyStruct
    {
        public byte MyByte;
        public NestedStruct MyNestedStruct;

        public struct NestedStruct
        {
            public byte NestedStructByte;
        }

        public MyStruct(byte[] bytes)
        {
            MyByte = bytes[0];
            MyNestedStruct.NestedStructByte = bytes[1];
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyStruct ms = new MyStruct(new byte[] { 1, 2 });
            //ms.MyByte; // 0, but should be 1
            //ms.MyNestedStruct.NestedStructByte; // 0, but should be 2

        }
    }