Читаем Linux программирование в примерах полностью

Нелокальные переходы осуществляются с помощью функций setjmp() и longjmp(). Эти функции используются в двух разновидностях. Традиционные процедуры определены стандартом ISO С:

#include /* ISO С */

int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

Тип jmp_buf определен через typedef в . setjmp() сохраняет текущее «окружение» в env. env обычно является глобальной или статической на уровне файла переменной, так что она может использоваться из вызванной функции. Это окружение включает любую информацию, необходимую для перехода на местоположение, из которого была вызвана setjmp(). Содержание jmp_buf по своей природе машинно-зависимо; таким образом, jmp_buf является непрозрачным типом: тем, что вы используете, не зная, что находится внутри него.

setjmp() возвращает 0, когда она вызывается для сохранения в jmp_buf текущего окружения. Ненулевое значение возвращается, когда с использованием окружения осуществляется нелокальный переход:

jmp_buf command_loop; /* На глобальном уровне */

/* ... затем в main() ... */

if (setjmp(command_loop) == 0) /* Состояние сохранено, продолжить */

 ;

else /* Мы попадаем сюда через нелокальный переход */

 printf("?\n"); /* ed's famous message */

/* ... теперь начать цикл команд ... */

longjmp() осуществляет переход. Первым параметром является jmp_buf, который должен быть инициализирован с помощью setjmp(). Второй является целым ненулевым значением, которое setjmp() возвращает в первоначальное окружение. Это сделано так, что код, подобный только что показанному, может различить установку окружения и прибытие путем нелокального перехода.

Стандарт С утверждает, что даже если longjmp() вызывается со вторым аргументом, равным 0, setjmp() по-прежнему возвращает ненулевое значение. В таком случае она возвращает 1.

Возможность передать целое значение и вернуться обратно из setjmp() полезна; это позволяет коду уровня пользователя различать причину перехода. Например, gawk использует эту возможность для обработки операторов break и continue внутри циклов. (Язык awk осознанно сделан похожим на С в своем синтаксисе для циклов, с использованием while, do-while, for, break и continue.) Использование setjmp() выглядит следующим образом (из eval.c в дистрибутиве gawk 3.1.3):

507 case Node_K_while:

508  PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);

509

510  stable_tree = tree;

511  while (eval_condition(stable_tree->lnode)) {

512   INCREMENT(stable_tree->exec_count);

513   switch (setjmp(loop_tag)) {

514   case 0: /* обычный не переход */

515    (void)interpret(stable_tree->rnode);

516    break;

517   case TAG_CONTINUE: /* оператор continue */

518    break;

519   case TAG_BREAK: /* оператор break */

520    RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);

521    return 1;

522   default:

523    cant_happen();

524   }

525  }

526  RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);

527  break;

Этот фрагмент кода представляет цикл while. Строка 508 управляет вложенными циклами посредством стека сохраненных переменных jmp_buf. Строки 511–524 выполняют цикл while (используя цикл С while!). Строка 511 проверяет условие цикла. Если оно истинно, строка 513 выполняет switch на возвращаемое значение setjmp(). Если оно равно 0 (строки 514–516), строка 515 выполняет тело оператора. Однако, когда setjmp() возвращает TAG_BREAK или TAG_CONTINUE, оператор switch обрабатывает их соответствующим образом (строки 517–518 и 519–521 соответственно).

Оператор break на уровне awk передает TAG_BREAK функции longjmp(), a continue уровня awk передает TAG_CONTINUE. Снова из eval.c с некоторыми пропущенными не относящимися к делу подробностями:

657 case Node_K_break:

658  INCREMENT(tree->exec_count);

     /* ... */

Перейти на страницу:

Похожие книги

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных