То, что вы разместили как «помеченное вручную», не является допустимым синтаксисом C, я полагаю, вы имели в виду:
typedef enum {INT,STRING} u_types;
typedef struct {
u_types tag;
union u{
int i;
char s[1];
} d;
}tagged_union;
Обратите внимание, что формальное определение тега struct / union в C - это имя после ключевого слова struc / union. Во втором примере u
- это тег union . Это то, что меня сильно смутило.
То, что вы описываете как «помеченное объединение», в компьютерной науке известно как вариант : переменная, которая может содержать несколько типов. Варианты обычно не одобряются в программировании в целом и в C в частности. Они запрещены в MISRA-C: 2004, правила 18.3 и 18.4.
Языки с поддержкой вариантов, таких как VB (и, возможно, Haskell?), Обычно представлены тогда как: эта переменная может содержать что угодно, но вы должны быть осторожны с ее использованием, поскольку она очень неэффективна.
В C варианты не только неэффективны, но и представляют угрозу безопасности. MISRA-c признает это в правиле 18.3:
Например: программа может попытаться получить доступ к данным одного типа из местоположения, когда на самом деле она хранит значение другого типа (например, из-за прерывания). Данные двух типов могут по-разному выравниваться в хранилище и посягать на другие данные. Поэтому данные не могут быть правильно инициализированы каждый раз, когда использование переключается. Эта практика особенно опасна в параллельных системах.
Таким образом, вопрос, скорее, должен быть: есть ли применение для теговых союзов (вариантов)? Нет, нет. Я не использовал ни одной программы на C, которую когда-либо писал, для них нет смысла. Поскольку C имеет пустые указатели, в C есть гораздо лучшие и более безопасные способы создания общих типов данных:
void ADT_add_generic_type (void* data, some_enum_t type, size_t size);
Посмотрите, как стандарт C реализует функции qsort () и bsearch (), для некоторых хороших примеров общего программирования на C (ISO 9899: 1999 7.20.5.1):
void *bsearch (const void *key,
const void *base,
size_t nmemb,
size_t size,
int (*compar)(const void *, const void *));
Описание Функция bsearch ищет массив объектов nmemb,
начальный элемент которого указан базой, для элемента
который соответствует объекту, указанному ключом. Размер каждого элемента
массив указан по размеру.
Однако для «нетегированных» союзов используется несколько. Протоколы данных, упаковка, доступ к аппаратному регистру и т. Д. И т. Д. Хороший пример приведен в ответе Дмитрия.