Преимущества использования объединения, когда то же самое может быть сделано с помощью структуры - C

Я испытываю затруднения в понимании использования union в C. Я считал партию сообщений здесь на ТАК о предмете. Но ни один из них не объясняет о почему union предпочтен, когда то же самое может быть достигнуто с помощью структуры.

Заключение в кавычки от K&R

Как пример тот, который мог бы быть найден в менеджере по таблице символов компилятора, предположить, что константа может быть интервалом, плаванием или символьным указателем. Значение конкретной константы должно быть сохранено в переменной надлежащего типа, все же является самым удобным для управления таблицей, если значение занимает ту же сумму устройства хранения данных и хранится в том же месте независимо от его типа. Это - цель объединения единственная переменная, которая может законно содержать любой один из нескольких типов. Синтаксис основан на структурах:

union u_tag {
      int ival;
      float fval;
      char *sval;
} u;

Использование будет

if (utype == INT)
    printf("%d\n", u.ival);
if (utype == FLOAT)
    printf("%f\n", u.fval);
if (utype == STRING)
    printf("%s\n", u.sval);
else
    printf("bad type %d in utype\n", utype);

То же самое может быть реализовано с помощью структуры. Что-то как,

struct u_tag {
    utype_t utype;
    int ival;
    float fval;
    char *sval;
} u;

if (u.utype == INT)
    printf("%d\n", u.ival);
if (u.utype == FLOAT)
    printf("%f\n", u.fval);
if (u.utype == STRING)
    printf("%s\n", u.sval);
else
    printf("bad type %d in utype\n", utype);

Разве это не то же? Какое преимущество union дает?

Какие-либо мысли?

6
задан timrau 15 August 2012 в 17:10
поделиться

10 ответов

В опубликованном вами примере размер объединения будет размером с плавающей точкой (при условии, что он самый большой - как указано в комментариях, он может варьироваться в 64-битном компиляторе), а размер структуры будет быть суммой размеров float, int, char * и utype_t (и отступов, если они есть).

Результаты моего компилятора:

union u_tag {
    int ival;
    float fval;
    char *sval;
};
struct s_tag {
    int ival;
    float fval;
    char *sval;
};

int main()
{
    printf("%d\n", sizeof(union u_tag));  //prints 4
    printf("%d\n", sizeof(struct s_tag)); //prints 12
    return 0;
}
9
ответ дан 8 December 2019 в 03:24
поделиться

Объединения можно использовать, когда требуется доступ не более чем к одному члену одновременно. Таким образом, вы можете сэкономить немного памяти вместо использования структуры.

Есть изящный «обман», который возможен с объединениями: запись одного поля и чтение из другого, чтобы проверять битовые шаблоны или интерпретировать их по-разному.

8
ответ дан 8 December 2019 в 03:24
поделиться

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

4
ответ дан 8 December 2019 в 03:24
поделиться

Объединения используются для одновременного сохранения только одного типа данных. Если значение переназначается, старое значение перезаписывается и становится недоступным. В вашем примере члены int, float и char могут иметь разные значения в любое время при использовании в качестве структуры. В союзе дело обстоит иначе. Так что это зависит от требований и дизайна вашей программы. Прочтите эту статью о том, когда использовать union. Google может дать еще больше результатов.

4
ответ дан 8 December 2019 в 03:24
поделиться

Язык предлагает программисту многочисленные возможности для применения абстракций высокого уровня к машинным данным и операциям самого низкого уровня.

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

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

В последнее время стоимость памяти была чрезвычайно низкой. Введение типа bool (и даже до этого переменных int) позволило программисту 32-битных систем использовать 32 бита для представления двоичного состояния. Вы видите это часто в программировании, даже если программист мог использовать маски и получить 32 истинных / ложных значения в переменной.

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

2
ответ дан 8 December 2019 в 03:24
поделиться

Как часто упоминалось ранее: объединения экономят память. Но это не единственная разница. Стыки созданы для сохранения ВСЕХ заданных подтипов, в то время как союзы созданы для сохранения ТОЧНО ОДИН из данных подтипов. Итак, если вы хотите сохранить целое число или число с плавающей запятой, то, вероятно, вам нужно объединение (но вам нужно где-то еще запомнить, какое число вы сохранили). Если вы хотите сохранить и то, и другое, вам понадобится структура.

0
ответ дан 8 December 2019 в 03:24
поделиться

заимствование из опубликованной вами цитаты «... любой из один из нескольких типов ...» членов профсоюза за раз. Это и есть союз; в то время как все члены структуры могут быть назначены и доступны одновременно.

union имеет больше смысла при выполнении некоторых программ системного уровня (ОС), таких как взаимодействие процессов / обработка параллелизма.

0
ответ дан 8 December 2019 в 03:24
поделиться

Использование союзов для экономии памяти в большинстве случаев не используется в современных системах, поскольку код для доступа к члену союза быстро займет больше места (и будет медленнее), чем просто добавление в память еще одной переменной размером в слово. Однако, когда ваш код должен поддерживать несколько архитектур с разными эндианальностями (ух, какое слово), союзы могут быть очень полезны. Я предпочитаю использовать библиотеку утилит endian (функции to), но некоторым людям нравятся союзы.

Доступ к аппаратным регистрам, отображенным на память, также часто осуществляется с помощью союзов. Битовые поля в C (не используйте их, они убогие) можно передавать как слова с помощью союзов.

1
ответ дан 8 December 2019 в 03:24
поделиться

союзы имеют два основных применения:

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

Я обычно встраиваю объединение в структуру - структура гарантирует, что тип и данные хранятся вместе, а объединение означает, что сохраняется ровно одно значение.

struct any_tag {
    utype_t utype;
    union {
        int ival;
        float fval;
        char *sval;
    } u;
} data;

Во-вторых, объединение отлично подходит для низкоуровневого доступа к необработанным данным - переосмысления одного типа как другого. Я использовал это для чтения и записи данных в двоичной кодировке.

float ConvertByteOrderedBufferTo32bitFloat( char* input ) {
union {
    float f;
    unsigned char buf[4];
} data;

#if WORDS_BIGENDIAN == 1
data.buf[0] = input[0];
data.buf[1] = input[1];
data.buf[2] = input[2];
data.buf[3] = input[3];
#else
data.buf[0] = input[3];
data.buf[1] = input[2];
data.buf[2] = input[1];
data.buf[3] = input[0];
#endif

return dat1.f;
}

Здесь вы можете записать в отдельные байты, в зависимости от порядка байтов платформы, а затем интерпретировать эти 4 необработанных байта char как плавающее значение IEEE. Преобразование этого массива char в float не даст того же результата.

1
ответ дан 8 December 2019 в 03:24
поделиться

Объединения - это сложно. В течение многих лет я не мог их понять, затем я начал делать что-то с сетевыми протоколами, и кто-то показал мне свет. Допустим, у вас есть заголовок, а затем после заголовка есть различные типы пакетов, например:

| тип (4 байта) | uid (8 байт) | длина полезной нагрузки (2 байта) | Payload (переменная длина) |

И тогда будут различные типы полезной нагрузки пакетов ... В качестве аргумента могут быть пакеты hello, goodbye и message ...

Ну, вы можете создать вложенный набор структур / объединений, которые могут точно представлять пакет в этом протоколе вот так ...

struct packet {
  uint type;
  char unique_id [8];
  ushort payload_length;
  union payload {

    struct hello {
      ushort version;
      uint status;
    };

    struct goodbye {
      char reason[20];
      uint status;
    };

    struct message {
      char message[100];
    };

  };
};

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

char buf[100];
packet *pkt;
read(outsideworld,&buf,1000);
pkt = (struct packet *)&buf;

и прочитать ваши пакеты это так же просто, как ...

switch(pkt->type){

  case PACKET_MESSAGE:
    printf("message = %s\n",
           pkt->payload.message.message);
    break;

  case PACKET_HELLO:
    printf("hello! version = %d status = %d\n",
           pkt->payload.hello.version,
           pkt->payload.hello.status);
    break;
  case PACKET_GOODBYE:
    printf("goodbye! reason = %s status = %d\n",
           pkt->payload.goodbye.reason,
           pkt->payload.goodbye.status);
    break;
}

Никакого пресмыкания, подсчета байтов и т. д. Вы можете вложить это так глубоко, как захотите (сделайте объединение для IP-адресов, что даст вам все в виде целого числа без знака или отдельные байты, чтобы было легче распечатать 192.168.0.1 из него).

Объединения не замедляют ваш код, потому что все это просто переводится в смещения в машинном коде.

0
ответ дан 8 December 2019 в 03:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: