Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
/* ...структуры для других типов операторов... */typedef enum stmt_type { IF, WHILE, FOR, ...} TYPE; /* Что у нас есть в действительности *//* Здесь содержатся тип и объединения отдельных видов операторов. */struct statement { TYPE type; union stmt { struct if_stmt if_st; struct while_stmt while_st; struct for_stmt for_st; ... } u;};Вместе с объединением удобно использовать макрос, который представляет компоненты объединения, как если бы они были полями структуры. Например:
#define if_s u.if_st /* Так что можно использовать s->if_s вместо s->u.if_st */#define while_s u.while_st /* И так далее... */#define for_s u.for_st...На только что представленном уровне это кажется разумным и выглядит осуществимым. В действительности, однако, все сложнее, и в реальных компиляторах и интерпретаторах часто есть несколько уровней вложенных структур и объединений. Сюда относится и
gawkNODEtypedef struct exp_node { union { struct { union { struct exp_node *lptr; char *param_name; long ll; } l; union { ... } r; union { ... } x; char *name; short number; unsigned long reflags; ... } nodep; struct { AWKNUM fltnum; char *sp; size_t slen; long sref; int idx; } val; struct { struct exp_node *next; char *name; size_t length; struct exp_node *value; long ref; } hash;#define hnext sub.hash.next#define hname sub.hash.name#define hlength sub.hash.length#define hvalue sub.hash.value ... } sub; NODETYPE type; unsigned short flags; ...} NODE;#define vname sub.nodep.name#define exec_count sub.nodep.reflags#define lnode sub.nodep.l.lptr#define nextp sub.nodep.l.lptr#define source_file sub.nodep.name#define source_line sub.nodep.number#define param_cnt sub.nodep.number#define param sub.nodep.l.param_name#define stptr sub.val.sp#define stlen sub.val.slen#define stref sub.val.sref#define stfmt sub.val.idx#define var_value lnode...В
NODEstructunionNODEПреимуществом такой сложности является то, что код С сравнительно ясный. Нечто вроде '
NF_node->var_value->slenУ такой гибкости, которую предоставляют объединения, конечно, есть своя цена. Когда отладчик находится глубоко во внутренностях вашего кода, вы не можете использовать симпатичные макросы, которые имеются в исходном коде. Вы должны использовать развернутое значение. [172] (А для этого придется найти в заголовочном файле соответствующее определение.)
Например, сравните '
NF_node->var_value->slenNF_node->sub.nodep.l.lptr->sub.val.slen(gdb) <b>print *tree</b> /* Вывести NODE */$1 = {sub = {nodep = {1 = {lptr = 0x8095598, param_name = 0x8095598 "xUtb", ll = 134829464}, r = {rptr = 0x0, pptr = 0, preg = 0x0, hd = 0x0, av = 0x0, r_ent =0), x = {extra = 0x0, xl = 0, param_list = 0x0}, name = 0x0, number = 1, reflags = 0},