Вот пример объединения из моей собственной кодовой базы (из памяти и перефразировано, поэтому оно может быть неточным). Он использовался для хранения языковых элементов в интерпретаторе, который я построил. Например, следующий код:
set a to b times 7.
состоит из следующих языковых элементов:
- символ [комплект]
- переменная [а]
- символ [к]
- переменная [Ь]
- символ [раз]
- постоянная [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 байта для объединения, хотя это типичные значения, размеры фактических зависят от реализации).
Чтобы создать элемент "set", вы должны использовать:
tElem e;
e.typ = ELEM_SYM_SET;
Чтобы создать элемент «variable [b]», вы должны использовать:
tElem e;
e.typ = ELEM_VARIABLE;
e.str = strdup ("b"); // make sure you free this later
Чтобы создать элемент «constant [7]», вы должны использовать:
tElem e;
e.typ = ELEM_CONSTANT;
e.val = 7;
, и вы можете легко расширить его, включив в него числа с плавающей точкой (float flt
) или рациональные числа (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 | |
+-------+