简体   繁体   中英

Why is this struct cleared after being created?

I have a struct that looks something like this:

[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;
    }
}

When I try to create a new instance of this struct, every byte field is set to 0.

in_addr temp = new in_addr(bytes);

I've stepped through the struct's constructor and verified that the bytes are indeed getting assigned to the fields. But when I step out of the constructor and check the value of temp , everything is 0.

What's causing this?

Because of these lines:

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

They are mapped to your 4 bytes via

[FieldOffsetAttribute(0)]
public Anonymous2 S_un_b;

[FieldOffsetAttribute(0)]
public Anonymous3 S_un_w;

I can't reproduce this; your code works for me. I'm using Mono but I very much doubt that this is a bug in the Microsoft C# compiler, it's more likely that you've got an error elsewhere.

I just tested this in VisualStudio 2008 using C# and got the expected output (1, 2).

Try posting the actual example code that you're having an issue with.

EDIT This is why example code can be bad ;)

Your issue was with the StructLayout.Explicit on Anonymous1 . Is there a particular reason that

  1. You did explicit instead of sequential and putting them in the order you wanted
  2. You left the indices as 0 for all of them

When I changed it to Sequential and removed the attributes, it worked fine for me.

EDIT 2 (Deleted)

EDIT 3

Your issue is with the assignment in the constructor. Not sure how I missed this. You don't need to set all of those variables, because your FieldOffset attribute makes them all stored in the same location. The struct itself is only occupying 4 bytes of memory (in theory, anyway). Whether you're accessing it via the int , the byte s, or the two short s, they all go to the same place. As a result, your first two sets of assignments (to the int and to the byte s) are redundant, and the last set (to the short s setting them to 0) clears out what you just did.

Unfortunately the C# compiler doesn't know this, so I'm sure you added the last assignment because it complained about the struct not being fully assigned. Add the dummy assignments first for the short s and the int , then assign the byte s explicitly from the array.

If you are using C# 3.0, just try the following:

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

That should work, and would alleviate the need to have a constructor in your struct. If you can't directly initialize the NestedStructByte, create it first:

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

I tested your code - everything is OK.

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

        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM