Setjmp wird verwendet, um eine Markierung an, wohin der Aufruf von longjump zurückkehren soll, er gibt 0 zurück, wenn er direkt aufgerufen wird, er gibt 1 zurück, wenn er aufgerufen wird, weil ein longjmp zu diesem setjmp aufgerufen wird.
Man muss sich setjmp wie etwas vorstellen, das normalerweise aufgerufen werden kann und im normalen Betrieb nichts tut (0 zurückgibt), während es 1 zurückgibt und indirekt aufgerufen wird (und von dort zurückkehrt), wenn ein Weitsprung aufgerufen wird. Ich weiß, was Sie mit verwirrend meinen, denn es ist tatsächlich verwirrend
Dies ist das Beispiel, das die Wikipedia angibt:
#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;
}
Sind Sie in der Lage, sie zu verstehen? Wenn das Programm gestartet wird setjmp
wird in main ausgeführt und gibt 0 zurück (weil es direkt aufgerufen wird), also first
aufgerufen wird, ruft das second
und dann kommt sie an longjmp
der den Kontext umschaltet und dorthin zurückkehrt, wo setjmp
verwendet, aber dieses Mal gibt die Funktion 1 zurück, da sie von einem Sprung zurückgeht und indirekt aufgerufen wird.
Das Nützliche am setjmp/longjmp-Ansatz ist, dass man mit Fehlersituationen umgehen kann, ohne sich um die Beibehaltung eines Flags zwischen Funktionsaufrufen kümmern zu müssen (vor allem, wenn man viele hat, man denke an eine rekursive Prozedur zur Typüberprüfung in einem Compiler). Wenn bei der Typüberprüfung tief im Aufrufstapel etwas schief geht, muss man normalerweise ein Flag zurückgeben und es immer wieder zurückgeben, um den Aufrufer zu warnen, dass die Typüberprüfung fehlgeschlagen ist. Mit longjmp Du gehst einfach los und behebst Fehler, ohne dich um die Rückgabe von Flaggen zu kümmern. Das einzige Problem ist, dass dies einen Kontextwechsel erzwingt, der sich nicht um die Standard-Deallokation von Stack/Heap-Speicher kümmert, so dass Sie dies selbst erledigen sollten.