Структуры и Союзы в C, определение размера и доступа к членам - PullRequest
3 голосов
/ 01 августа 2010

Все,

Вот пример для союзов, который я нахожу сбивающим с толку.

struct s1
{
    int a;
    char b;
    union
    {
       struct
       {
          char *c;
          long d;
       }
       long e;
     }var;
};

Учитывая, что char равен 1 байту, int равен 2 байта и long4 байта.Каков будет размер всей структуры здесь?Будет ли размер объединения {size of char *} + {size of double}?Я смущен из-за структуры, объединенной в союз.

Кроме того, как я могу получить доступ к переменной d в структуре.var.d?

Ответы [ 3 ]

5 голосов
/ 01 августа 2010

Размеры определяются реализацией из-за заполнения.Объединение будет по крайней мере размером с наибольший член, в то время как структура будет по крайней мере суммой размеров членов.Внутренняя структура будет на минимум sizeof(char *) to sizeof(long), поэтому объединение будет по крайней мере настолько большим.Внешняя структура будет по крайней мере sizeof(int) + 1 + sizeof(char *) + sizeof(long).Все структуры и объединения могут иметь отступы.

Вы используете расширение к стандартному, неназванным полям .В ISO C не было бы никакого доступа к внутренней структуре.Но в GCC (и я полагаю, MSVC) вы можете сделать var.d.

Кроме того, вам не хватает точки с запятой после внутренней структуры.

1 голос
/ 01 августа 2010

Без заполнения и при условии, что sizeof (int) == sizeof (char *) == sizeof (long) == 4, размер внешней структуры будет 13.

Разбить его,объединение var перекрывает анонимную структуру с одним long.Эта внутренняя структура больше (указатель и long), поэтому ее размер управляет размером объединения, в результате чего объединение занимает 8 байтов.Остальные члены имеют 4 байта и 1 байт, поэтому общее количество равно 13.

В любой разумной реализации с предположениями о размере, которые я сделал выше, эта структура будет дополнена границами 2 или 4 байта, добавляя вкак минимум 1 или 3 дополнительных байта к размеру.

Редактировать: В общем, поскольку размеры всех типов элементов сами по себе определены реализацией, а заполнение определяется реализацией, вам необходимочтобы обратиться к документации по вашей реализации и платформе, чтобы знать наверняка.

Реализации разрешено вставлять заполнение после практически любого элемента структуры.Разумные реализации используют минимальное заполнение, необходимое для соответствия требованиям платформы (например, процессоры RISC часто требуют, чтобы значение было выровнено по размеру этого значения) или для производительности.

Если используется структура для сопоставления полей скомпоновка значений, предполагаемая спецификацией формата файла, сопроцессором в разделяемой памяти, аппаратным устройством или любым другим подобным случаем, когда упаковка и компоновка действительно имеют значение, тогда вы можете быть обеспокоены тем, что вы тестируете во время компиляции или во время выполненияВаши предположения о макете члена верны.Это можно сделать, проверив размер всей структуры, а также смещения ее членов.

См. этот вопрос среди других для обсуждения приемов утверждения во время компиляции.

0 голосов
/ 01 августа 2010

Союзы опасны и рискованно использовать без строгой дисциплины.И тот факт, что вы помещаете его в структуру, действительно опасен, потому что по умолчанию все члены структуры являются открытыми: это предоставляет возможность клиентскому коду вносить изменения в ваш союз, не сообщая вашей программе, какой тип данных он там вставил.Если вы используете профсоюз, вы должны поместить его в класс, где, по крайней мере, вы можете спрятать его, сделав его закрытым.

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

Кроме того, союзы отбрасывают все типы безопасности, которые современные c/ C ++ компиляторы дают вам.Конечно, если вы врете компилятору, он когда-нибудь ответит вам.Ну, на самом деле, он вернется к вашему клиенту, когда ваше приложение выйдет из строя.

...