====== setjmp.h ======
заголовочник объявляющий макросы и тип данных для нелокальных переходов. В Си существует оператор goto, позволяющий переходить в любое место в пределах функции (с некоторыми оговорками), однако переход между функциями с его помощью невозможен.
определения:
#include
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
описание:
* ''jmp_buf'' — тип данных, представляющий сохранённое состояние выполнения (контекст), включая регистры, указатель стека и указатель инструкции. Размер и содержимое зависят от реализации.
* ''setjmp(env)'' — (по простому - сохраняет точку возврата) сохраняет текущий контекст в env и возвращает 0 при прямом вызове. При последующем возвращении, инициированном longjmp, setjmp возвращает ненулевое значение, переданное в longjmp.
* ''longjmp(env, val)'' — (по простому - возвращаеться в точку возврата) восстанавливает контекст, ранее сохранённый в env, и заставляет ранее вызванный setjmp((Если функция была вызвана без соответствующего вызова setjmp(), или функция, в которой восстанавливается выполнение, уже завершилась, то поведение не определено.)) вернуться с значением val (если val == 0, оно преобразуется в 1). Выполнение продолжается как будто setjmp только что вернуло это значение.
наглядное объяснение: {{:c:c_ultimate_guide:2025-10-31_13-23.png}}
Использование setjmp() и longjmp() может привести к утечкам памяти, если выделение происходит между вызовами этих функций.
О памяти:
* глобальные сохраняються
* динамическая память остаеться как была
* файлы и т.п. остаються как были
* локальные непредсказуемы (если только их жестко не привязать к памяти через ''volatile''(никаких регистров и прочих оптимизаций))
пример:
#include
#include
static jmp_buf buf;
void second(void) {
printf("вторая функция: собираюсь longjmp\n");
longjmp(buf, 42);
}
void first(void) {
second();
printf("это не будет выполнено\n");
}
int main(void) {
int val = setjmp(buf);
if (val == 0) {
printf("setjmp вернул 0 — нормальный путь\n");
first();
} else {
printf("setjmp вернул %d — вернулись из longjmp\n", val);
}
return 0;
}