Почему нам нужны Объединения C?

222
задан timrau 14 August 2012 в 06:49
поделиться

7 ответов

Объединения часто используются для преобразования между двоичными представлениями целых чисел и плаваний:

union
{
  int i;
  float f;
} u;

// Convert floating-point bits to integer:
u.f = 3.14159f;
printf("As integer: %08x\n", u.i);

, Хотя это - технически неопределенное поведение согласно стандарту C (Вы, как только предполагается, читаете поле, которое было последний раз записано), это будет действовать четко определенным способом в фактически любом компиляторе.

Объединения также иногда используются для реализации псевдополиморфизма в C путем предоставления структуре некоторого тега, указывающего, какой объект это содержит, и затем unioning возможные типы вместе:

enum Type { INTS, FLOATS, DOUBLE };
struct S
{
  Type s_type;
  union
  {
    int s_ints[2];
    float s_floats[2];
    double s_double;
  };
};

void do_something(struct S *s)
{
  switch(s->s_type)
  {
    case INTS:  // do something with s->s_ints
      break;

    case FLOATS:  // do something with s->s_floats
      break;

    case DOUBLE:  // do something with s->s_double
      break;
  }
}

Это позволяет размеру struct S составлять только 12 байтов, вместо 28.

242
ответ дан rubenvb 23 November 2019 в 04:01
поделиться

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

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

union Event
{
  unsigned long eventCode;
  unsigned char eventParts[4];
};
1
ответ дан dicroce 23 November 2019 в 04:01
поделиться

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

4
ответ дан Ana Betts 23 November 2019 в 04:01
поделиться

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

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

, Например:

typedef union MyUnion MYUNION;
union MyUnion
{
   int MyInt;
   float MyFloat;
};

MyUnion будет только содержать интервал ИЛИ плавание, , в зависимости от которого Вы последний раз устанавливаете . Так выполнение этого:

MYUNION u;
u.MyInt = 10;

u теперь содержит интервал, равный 10;

u.MyFloat = 1.0;

u теперь содержит плавание, равное 1,0. Это больше не содержит интервал, Очевидно, теперь, при попытке сделать printf ("MyInt = % d", u. MyInt); тогда Вы, вероятно, собираетесь получить ошибку, хотя я не уверен в определенном поведении.

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

5
ответ дан Xiaofu 23 November 2019 в 04:01
поделиться

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

set a to b times 7.

состоит из следующих элементов языка:

  • символ [установил]
  • переменная
  • символ [к] [1 117]
  • переменный символ [времена] [b]
  • постоянный [7]
  • символ [.]

, элементы Языка были, определяет как' #define' значения таким образом:

#define ELEM_SYM_SET        0
#define ELEM_SYM_TO         1
#define ELEM_SYM_TIMES      2
#define ELEM_SYM_FULLSTOP   3
#define ELEM_VARIABLE     100
#define ELEM_CONSTANT     101

и следующая структура использовался для хранения каждого элемента:

typedef struct {
    int typ;
    union {
        char *str;
        int   val;
    }
} tElem;

тогда размер каждого элемента был размером максимального объединения (4 байта для типа и 4 байта для объединения, хотя те - типичные значения, фактический размеры cepend на реализации).

для создания элемента "набора", Вы использовали бы:

tElem e;
e.typ = ELEM_SYM_SET;

для создания "переменной [b]" элемент, Вы использовали бы:

tElem e;
e.typ = ELEM_VARIABLE;
e.str = strdup ("b");   // make sure you free this later

для создания "константы [7]" элемент, Вы использовали бы:

tElem e;
e.typ = ELEM_CONSTANT;
e.val = 7;

и Вы могли легко развернуть его для включения плаваний (float flt) или rationals (struct ratnl {int num; int denom;}) и другие типы.

основная предпосылка - то, что str и val не непрерывны в памяти, они на самом деле накладываются, таким образом, это - способ получить другое представление относительно того же блока памяти, проиллюстрированной здесь, где структура базируется в ячейке памяти 0x1010 и целые числа, и указатели - оба 4 байта:

       +-----------+
0x1010 |           |
0x1011 |    typ    |
0x1012 |           |
0x1013 |           |
       +-----+-----+
0x1014 |     |     |
0x1015 | str | val |
0x1016 |     |     |
0x1017 |     |     |
       +-----+-----+

, Если бы это было только в структуре, это было бы похоже на это:

       +-------+
0x1010 |       |
0x1011 |  typ  |
0x1012 |       |
0x1013 |       |
       +-------+
0x1014 |       |
0x1015 |  str  |
0x1016 |       |
0x1017 |       |
       +-------+
0x1018 |       |
0x1019 |  val  |
0x101A |       |
0x101B |       |
       +-------+
17
ответ дан paxdiablo 23 November 2019 в 04:01
поделиться

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

В следующем примере:

union {
   int a;
   int b;
   int c;
} myUnion;

Это объединение займет место единственного интервала, а не 3 отдельных международных значения. Если пользователь установил значение , и затем установил значение b, это перезаписало бы значение , так как они оба совместно используют ту же ячейку памяти.

29
ответ дан LeopardSkinPillBoxHat 23 November 2019 в 04:01
поделиться

Объединения особенно полезны во Встроенном программировании или в ситуациях, где прямой доступ к аппаратным средствам/памяти необходим. Вот тривиальный пример:

typedef union
{
    struct {
        unsigned char byte1;
        unsigned char byte2;
        unsigned char byte3;
        unsigned char byte4;
    } bytes;
    unsigned int dword;
} HW_Register;
HW_Register reg;

Тогда можно получить доступ к reg следующим образом:

reg.dword = 0x12345678;
reg.bytes.byte3 = 4;

Порядок байтов (порядок байтов) и архитектура процессора, конечно, важен.

Другой полезной функцией является разрядный модификатор:

typedef union
{
    struct {
        unsigned char b1:1;
        unsigned char b2:1;
        unsigned char b3:1;
        unsigned char b4:1;
        unsigned char reserved:4;
    } bits;
    unsigned char byte;
} HW_RegisterB;
HW_RegisterB reg;

С этим кодом можно получить доступ непосредственно к единственному биту в регистре/адресе памяти:

x = reg.bits.b2;
127
ответ дан torrential coding 23 November 2019 в 04:01
поделиться
Другие вопросы по тегам:

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