Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Интернет » Linux программирование в примерах - Роббинс Арнольд

Linux программирование в примерах - Роббинс Арнольд

Читать онлайн Linux программирование в примерах - Роббинс Арнольд

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 224 225 226 227 228 229 230 231 232 ... 253
Перейти на страницу:

На практике фиксированный размер также не является проблемой; мы знаем, что размер BUFSIZ достаточен для представления всех флагов, которые мы используем. Тем не менее, поскольку мы опытные и знаем, что вещи могут измениться, в getflags2str() есть код, предохраняющий себя от переполнения буфера. (Переменная space_left и код в строках 18–20.)

В качестве отступления, использование BUFSIZ спорно. Эта константа должна использоваться исключительно для буферов ввода/вывода, но часто она используется также для общих строковых буферов. Такой код лучше убрать, определив явные константы, такие, как FLAGVALSIZE, и использовав в строке 11 'sizeof (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 &quot;hello, world&quot; }'</b> /* Запустить программу */

Starting program: /home/arnold/Gnu/gawk/gawk-3.1.4/gawk 'BEGIN { print &quot;hello, world&quot; }'

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 &quot;xUtb&quot;,

 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-&gt;flags)</b> /* Вывести значение флага */

$2 = 0x80918a0 &quot;MALLOC&quot;

(gdb) <b>next</b> /* Продолжить */

1553 fp = redirect_to_fp(tree-&gt;rnode, &amp;rp);

...

1588 efwrite(t[i]-&gt;stptr, sizeof(char), t[i]-&gt;stlen, fp, &quot;print&quot;, rp, FALSE);

(gdb) <b>print *t[i]</b> /* Снова вывести NODE */

$4 = {sub = {nodep =

 {l = {lptr = 0x8095598, parm_name = 0x8095598 &quot;xUtb&quot;,

 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 &lt;Address 0xc out of bounds&gt;,

 number = 1, reflags = 4294967295}, val = {

 fltnum = 6.6614606209589101e-316, sp = 0x8095ad8 &quot;hello, world&quot;,

 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]-&gt;flags)</b> /* Вывести значение флага */

$5 = 0x80918a0 &quot;MALLOC|PERM|STRING|STRCUR&quot;

Надеемся, вы согласитесь, что настоящий механизм общего назначения значительно более элегантный и более простой в использовании, чем первоначальный.

Тщательное проектирование и использование массивов структур часто может заменить или слить воедино повторяющийся код.

15.4.1.5. По возможности избегайте объединений

«Не бывает бесплатных обедов»

- Lazarus Long -

union С относительно эзотерическая возможность. Она помогает экономить память, сохраняя различные элементы в одном и том же физическом пространстве; как программа интерпретирует его, зависит от способа доступа:

/* ch15-union.c --- краткая демонстрация использования union. */

#include &lt;stdio.h&gt;

int main(void) {

 union i_f {

  int i;

  float f;

 } u;

 u.f = 12.34; /* Присвоить значение с плавающей точкой */

 printf(&quot;%f also looks like %#xn&quot;, u.f, u.i};

 exit(0);

}

Вот что происходит, когда программа запускается на системе Intel x86 GNU/Linux:

$ <b>ch15-union</b>

12.340000 also looks like 0x414570a4

Программа выводит битовый паттерн, который представляет число с плавающей точкой в виде шестнадцатеричного целого. Оба поля занимают одно и то же место в памяти; разница в том, как этот участок памяти интерпретируется: u.f действует, как число с плавающей точкой, тогда как эти же биты в u.i действуют, как целое число.

Объединения особенно полезны в компиляторах и интерпретаторах, которые часто создают древовидные структуры, представляющие структуру файла с исходным кодом (которая называется деревом грамматического разбора (parse tree)). Это моделирует то, как формально описаны языки программирования: операторы if, операторы while, операторы присваивания и так далее для всех экземпляров более общего типа «оператора». Таким образом, в компиляторе могло бы быть нечто подобное этому:

struct if_stmt { ... }; /* Структура для оператора IF */

struct while_stmt { ... }; /* Структура для оператора WHILE */

struct for_stmt { ... }; /* Структура для оператора */

1 ... 224 225 226 227 228 229 230 231 232 ... 253
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Роббинс Арнольд.
Комментарии