Вход/Регистрация
Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

#define while_s u.while_st /* И так далее... */

#define for_s u.for_st

...

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

gawk
, в котором определение
NODE
, значение его флагов и макросов для доступа к компонентам объединения занимают свыше 120 строк! [171] Здесь достаточно определений, чтобы дать вам представление о том, что происходит:

171

Мы унаследовали эту схему. В общем, она работает, но все же есть проблемы. Целью данного раздела является передача накопленного нами в ходе работы с объединениями опыта — Примеч. автора.

typedef 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

...

В

NODE
есть объединение внутри структуры внутри объединения внутри структуры! (Ой.) Поверх всего этого многочисленные «поля» макросов соответствуют одним и тем же компонентам
struct
/
union
в зависимости от того, что на самом деле хранится в
NODE
! (Снова ой.)

Преимуществом такой сложности является то, что код С сравнительно ясный. Нечто вроде '

NF_node->var_value->slen
' читать просто.

У такой гибкости, которую предоставляют объединения, конечно, есть своя цена. Когда отладчик находится глубоко во внутренностях вашего кода, вы не можете использовать симпатичные макросы, которые имеются в исходном коде. Вы должны использовать развернутое значение. [172] (А для этого придется найти в заголовочном файле соответствующее определение.)

172

Опять-таки, GCC 3.1 или более новый и GDB 5 дают возможность непосредственного использования макросов, но только лишь если вы используете их совместно, с определенными опциями. Это было описано ранее в разделе 15.4.1.2 «По возможности избегайте макросов с выражениями». — Примеч. автора.

Например, сравните '

NF_node->var_value->slen
' с развернутой формой: '
NF_node->sub.nodep.l.lptr->sub.val.slen
'! Чтобы увидеть значение данных, вы должны набрать последнее в GDB. Взгляните снова на это извлечение из приведенного ранее сеанса отладки GDB:

(gdb) print *tree /* Вывести NODE */

$1 = {sub = {nodep =

 {1 = {lptr = 0x8095598, param_name = 0x8095598 "xU\t\b",

 ll = 134829464}, r = {rptr = 0x0, pptr = 0, preg = 0x0,

  • Читать дальше
  • 1
  • ...
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: