David Brown
David Brown

Reputation: 36239

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?

Upvotes: 0

Views: 281

Answers (5)

Adam Robinson
Adam Robinson

Reputation: 185583

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 bytes, or the two shorts, they all go to the same place. As a result, your first two sets of assignments (to the int and to the bytes) are redundant, and the last set (to the shorts 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 shorts and the int, then assign the bytes explicitly from the array.

Upvotes: 1

Mike Polen
Mike Polen

Reputation: 3596

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;

Upvotes: 5

den123
den123

Reputation: 801

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

        }
    }

Upvotes: 0

jrista
jrista

Reputation: 32950

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

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545488

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.

Upvotes: 3

Related Questions