Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
На практике фиксированный размер также не является проблемой; мы знаем, что размер
BUFSIZgetflags2str()space_leftВ качестве отступления, использование
BUFSIZFLAGVALSIZEsizeof (buffer)Вот сокращенный сеанс GDB, показывающий использование
flags2str()$ <b>gdb gawk</b> /* Запустить GDB с gawk */GNU gdb 5.3...(gdb) <b>break do_print</b> /* Установить контрольную точку */Breakpoint 1 at 0x805a584: file builtin.c, line 1547.(gdb) <b>run 'BEGIN { print "hello, world" }'</b> /* Запустить программу */Starting program: /home/arnold/Gnu/gawk/gawk-3.1.4/gawk 'BEGIN { print "hello, world" }'Breakpoint 1, do_print (tree=0x80955b8) at builtin.c: 1547 /* Останова в контрольной точке */1547 struct redirect *rp = NULL;(gdb) <b>print *tree</b> /* Вывести NODE */$1 = {sub = {nodep = {1 = {lptr = 0x8095598, param_name = 0x8095598 "xUtb", ll = 134629464}, 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), val = { fltnum = 6.6614606209589101e-316, sp = 0x0, slen = 0, sref = 1, idx = 0}, hash = {next = 0x8095598, name = 0x0, length = 0, value = 0x0, ref = 1}}, type = Node_K_print, flags = 1}(gdb) <b>print flags2str(tree->flags)</b> /* Вывести значение флага */$2 = 0x80918a0 "MALLOC"(gdb) <b>next</b> /* Продолжить */1553 fp = redirect_to_fp(tree->rnode, &rp);...1588 efwrite(t[i]->stptr, sizeof(char), t[i]->stlen, fp, "print", rp, FALSE);(gdb) <b>print *t[i]</b> /* Снова вывести NODE */$4 = {sub = {nodep = {l = {lptr = 0x8095598, parm_name = 0x8095598 "xUtb", ll = 134829464}, r = {rptr = 0x0, pptr = 0, preg = 0x0, hd = 0x0, av = 0x0, r_ent =0), x = {extra = 0x8095ad8, xl = 134830808, param_list = 0x8095ad8}, name = 0xc <Address 0xc out of bounds>, number = 1, reflags = 4294967295}, val = { fltnum = 6.6614606209589101e-316, sp = 0x8095ad8 "hello, world", slen = 12, sref = 1, idx = -1}, hash = {next = 0x8095598, name = 0x0, length = 134830808, value = 0xc, ref = 1}}, type = Node_val, flags = 29}(gdb) <b>print flags2str(t[i]->flags)</b> /* Вывести значение флага */$5 = 0x80918a0 "MALLOC|PERM|STRING|STRCUR"Надеемся, вы согласитесь, что настоящий механизм общего назначения значительно более элегантный и более простой в использовании, чем первоначальный.
Тщательное проектирование и использование массивов структур часто может заменить или слить воедино повторяющийся код.
15.4.1.5. По возможности избегайте объединений
«Не бывает бесплатных обедов»
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 %#xn", u.f, u.i}; exit(0);}Вот что происходит, когда программа запускается на системе Intel x86 GNU/Linux:
$ <b>ch15-union</b>12.340000 also looks like 0x414570a4Программа выводит битовый паттерн, который представляет число с плавающей точкой в виде шестнадцатеричного целого. Оба поля занимают одно и то же место в памяти; разница в том, как этот участок памяти интерпретируется:
u.fu.iОбъединения особенно полезны в компиляторах и интерпретаторах, которые часто создают древовидные структуры, представляющие структуру файла с исходным кодом (которая называется деревом грамматического разбора (parse tree)). Это моделирует то, как формально описаны языки программирования: операторы
ifwhilestruct if_stmt { ... }; /* Структура для оператора IF */struct while_stmt { ... }; /* Структура для оператора WHILE */struct for_stmt { ... }; /* Структура для оператора */