Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

12.5. Нелокальные переходы

«Идите прямо в тюрьму. Не проходите GO. Не забирайте 200$».

– Монополия -

Вы, без сомнения, знаете, чем является

goto
: передачей потока управления на метку где-то в текущей функции. Операторы
goto
при скупом употреблении могут послужить удобочитаемости и правильности функции (Например, когда все проверки ошибок используют
goto
для перехода на метку в конце функции, такую, как
clean_up
, код с этой меткой проводит очистку [закрывая файлы и т.п.] и возвращается.) При плохом использовании операторы
goto
могут привести к так называемой «лапше» в коде, логику которого становится невозможно отследить.

Оператор

goto
в языке С ограничен переходом на метку в текущей функции. Многие языки в семействе Алгола, такие, как Паскаль, допускают использование
goto
для выхода из вложенной функции в предшествующую вызывающую функцию. Однако в С нет способа, в пределах синтаксиса самого языка, перейти в определенную точку другой функции, пусть даже и вызывающей. Такой переход называется нелокальным переходом.

Почему полезен нелокальный переход? Рассмотрите интерактивную программу, которая считывает и выполняет программы. Предположим, пользователь запускает длительное задание, разочаровывается или меняет мнение о данном задании и нажимает CTRL-С для генерирования сигнала

SIGINT
. Когда запускается обработчик сигнала, он может перейти обратно в начало главного цикла чтения и обработки команд. Строковый редактор ed представляет простой пример этого:

$ ed -p '> ' sayings /* Запуск ed, '> ' используется как приглашение */

sayings: No such file or directory

> a /* Добавить текст */

Hello, world

Don't panic

^C /* Сгенерировать SIGINT */

? /* Сообщение об ошибке ''один размер подходит всем'' */

> 1,$p /* ed возвращается в командную строку */

Hello, world /* '1,$p' prints all the lines */

Don't panic

> w /* Сохранить файл */

25

> q /* Все сделано */

Внутри себя

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

12.5.1. Использование стандартных функций:

setjmp
и
longjmp

Нелокальные переходы осуществляются с помощью функций

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

#include <setjmp.h> /* ISO С */

int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

Тип

jmp_buf
определен через
typedef
в
<setjmp.h>
.
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);

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

Политолог

Проханов Александр Андреевич
Проза:
современная проза
5.20
рейтинг книги
Политолог

Заговор «Аквитания»

Ладлэм Роберт
Детективы:
политические детективы
5.00
рейтинг книги
Заговор «Аквитания»

Инкарнатор

Прокофьев Роман Юрьевич
1. Стеллар
Фантастика:
боевая фантастика
рпг
7.30
рейтинг книги
Инкарнатор

Виктимология. Психология поведения жертвы

Малкина-Пых Ирина Германовна
Научно-образовательная:
психология
5.75
рейтинг книги
Виктимология. Психология поведения жертвы

Звездный свет (сборник)

Клемент Хол
Классика мировой фантастики
Фантастика:
научная фантастика
6.25
рейтинг книги
Звездный свет (сборник)

Война

Валериев Игорь
7. Ермак
Фантастика:
боевая фантастика
альтернативная история
5.25
рейтинг книги
Война

Гобелены Фьонавара (сборник)

Кей Гай Гэвриел
Гобелены Фьонавара
Фантастика:
фэнтези
эпическая фантастика
6.25
рейтинг книги
Гобелены Фьонавара (сборник)

Князь Мещерский

Дроздов Анатолий Федорович
3. Зауряд-врач
Фантастика:
альтернативная история
8.39
рейтинг книги
Князь Мещерский

Воронцов. Перезагрузка. Книга 4

Тарасов Ник
4. Воронцов. Перезагрузка
Фантастика:
попаданцы
альтернативная история
фэнтези
фантастика: прочее
6.00
рейтинг книги
Воронцов. Перезагрузка. Книга 4

Чужая семья генерала драконов

Лунёва Мария
6. Генералы драконов
Фантастика:
фэнтези
5.25
рейтинг книги
Чужая семья генерала драконов

Религия и этика в изречениях и цитатах. Справочник

Душенко Константин Васильевич
Религия и эзотерика:
религия
5.00
рейтинг книги
Религия и этика в изречениях и цитатах. Справочник

Афганский полигон

Кулаков Сергей Федорович
Спецназ. Группа Антитеррор
Детективы:
боевики
6.17
рейтинг книги
Афганский полигон

"Фантастика 2025-103". Компиляция. Книги 1-17

Поселягин Владимир Геннадьевич
Фантастика 2025. Компиляция
Фантастика:
боевая фантастика
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Фантастика 2025-103. Компиляция. Книги 1-17

Рассвет русского царства 3

Грехов Тимофей
3. Новая Русь
Фантастика:
историческое фэнтези
альтернативная история
5.00
рейтинг книги
Рассвет русского царства 3