Почему эта структура очищается после создания? - PullRequest
0 голосов
/ 24 августа 2009

У меня есть структура, которая выглядит примерно так:

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

Я прошел через конструктор структуры и убедился, что байты действительно присваиваются полям. Но когда я выхожу из конструктора и проверяю значение temp, все равно 0.

Что вызывает это?

Ответы [ 5 ]

5 голосов
/ 24 августа 2009

Из-за этих строк:

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;
3 голосов
/ 24 августа 2009

Я не могу воспроизвести это; Ваш код работает для меня. Я использую Mono, но я очень сомневаюсь, что это ошибка в компиляторе Microsoft C #, более вероятно, что у вас есть ошибка в другом месте.

1 голос
/ 24 августа 2009

Я только что проверил это в VisualStudio 2008 с использованием C # и получил ожидаемый результат (1, 2).

Попробуйте опубликовать пример кода, с которым у вас возникли проблемы.

РЕДАКТИРОВАТЬ Вот почему пример кода может быть плохим;)

Ваша проблема была с StructLayout.Explicit на Anonymous1. Есть ли конкретная причина, по которой

  1. Вы сделали явное вместо последовательного и расположили их в нужном вам порядке
  2. Вы оставили индексы равными 0 для всех из них

Когда я изменил его на Sequential и удалил атрибуты, он работал нормально для меня.

РЕДАКТИРОВАТЬ 2 (удалено)

РЕДАКТИРОВАТЬ 3

Ваша проблема с заданием в конструкторе. Не уверен, как я это пропустил. Вам не нужно устанавливать все эти переменные, потому что ваш атрибут FieldOffset хранит их все в одном месте. Сама структура занимает только 4 байта памяти (теоретически, во всяком случае). Получаете ли вы доступ к нему через int, byte s или через два short s, все они идут в одно и то же место. В результате ваши первые два набора назначений (int и byte s) являются избыточными, а последний набор (для short s, устанавливающий их в 0) удаляет то, что вы только что сделали.

К сожалению, компилятор C # не знает этого, поэтому я уверен, что вы добавили последнее назначение, потому что он жаловался на то, что структура не была полностью назначена. Сначала добавьте фиктивные назначения для short s и int, затем явным образом назначьте byte s из массива.

0 голосов
/ 24 августа 2009

Я проверил ваш код - все ок.

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

        }
    }
0 голосов
/ 24 августа 2009

Если вы используете 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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...