length = 134830808, value = 0xc, ref = 1}}, type = Node_val, flags = 29}
(gdb) print flags2str(t[i]->flags) /*
Вывести значение флага */
$5 = 0x80918a0 "MALLOC|PERM|STRING|STRCUR"
Надеемся, вы согласитесь, что настоящий механизм общего назначения значительно более элегантный и более простой в использовании, чем первоначальный.
Тщательное проектирование и использование массивов структур часто может заменить или слить воедино повторяющийся код.
15.4.1.5. По возможности избегайте объединений
«Не бывает бесплатных обедов»
– Lazarus Long -
union
С относительно эзотерическая возможность. Она помогает экономить память, сохраняя различные элементы в одном и том же физическом пространстве; как программа интерпретирует его, зависит от способа доступа:
/* ch15-union.c --- краткая демонстрация использования union. */
#include <stdio.h>
int main(void) {
union i_f {
int i;
float f;
} u;
u.f = 12.34; /* Присвоить значение с плавающей точкой */
printf("%f also looks like %#x\n", u.f, u.i};
exit(0);
}
Вот что происходит, когда программа запускается на системе Intel x86 GNU/Linux:
$ ch15-union
12.340000 also looks like 0x414570a4
Программа выводит битовый паттерн, который представляет число с плавающей точкой в виде шестнадцатеричного целого. Оба поля занимают одно и то же место в памяти; разница в том, как этот участок памяти интерпретируется:
u.f
действует, как число с плавающей точкой, тогда как эти же биты в
u.i
действуют, как целое число.
Объединения особенно полезны в компиляторах и интерпретаторах, которые часто создают древовидные структуры, представляющие структуру файла с исходным кодом (которая называется деревом грамматического разбора (parse tree)). Это моделирует то, как формально описаны языки программирования: операторы
if
, операторы
while
, операторы присваивания и так далее для всех экземпляров более общего типа «оператора». Таким образом, в компиляторе могло бы быть нечто подобное этому: