setjmp используется для размещения маркера , где должен возвращаться вызов longjump, он возвращает 0, если он вызывается напрямую, он возвращает 1, если он вызван, потому что вызывается longjmp для этого setjmp.
Вы должны думать о том, что setjmp как-то нормально вызывается и ничего не делает (возвращает 0) в нормальной работе, а возвращает 1, и он косвенно называется (и возвращается оттуда), когда вызывается длинный прыжок. Я знаю, что вы имеете в виду о запутанным, потому что на самом деле это заблуждение ..
Это пример, приведенный википедии:
#include <stdio.h>
#include <setjmp.h>
static jmp_buf buf;
void second(void)
{
printf("second\n"); // prints
longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
}
void first(void)
{
second();
printf("first\n"); // does not print
}
int main()
{
if (! setjmp(buf))
{
first(); // when executed, setjmp returns 0
}
else
{ // when longjmp jumps back, setjmp returns 1
printf("main"); // prints
}
return 0;
}
в состоянии понять это Вы? При запуске программы setjmp
выполняется в основном и возвращает 0 (потому что он непосредственно вызывается), поэтому вызывается first
, который вызывает second
, а затем он принимает longjmp
, который переключает контекст, возвращаясь туда, где использовался setjmp
, но на этот раз, поскольку он возвращается из прыжка, и это косвенно называется возвратом функции 1.
Полезная вещь подхода setjmp/longjmp заключается в том, что вы можете обрабатывать ситуации с ошибками, не заботясь о том, чтобы держать флаг между вызовами функций (особенно, когда у вас много , подумайте о рекурсивной процедуре для проверки типов в компиляторе). Если что-то пойдет не так, как правило, в методе проверки стека вызовов в стеке, вы должны вернуть флаг и продолжать его возвращать, чтобы предупредить вызывающего абонента о том, что проверка typecheck не удалась. С longjmp вы просто выходите и обрабатываете ошибку, не заботясь о пропущенных флажках. Единственная проблема заключается в том, что это приводит к переключению контекста, который не заботится о стандартном освобождении памяти стека/кучи, поэтому вы должны обращаться с ним самостоятельно.
awesome man, thanks –
LongJmp как throw, и он называется сразу после того места, где может быть поднято исключение. А также почему вы используете номер 42, вы можете выполнить одно и то же задание 1 или 42 любой ненулевой положительный int. –
Ключевым моментом является то, что функция setjmp() может возвращаться один раз или может возвращаться несколько раз. Он вернется один раз из «прямого вызова» (который вернет 0); любые последующие возвращения являются результатом longjmp() и возвращают ненулевое значение. –