この関数の目的
longjmp()
は、 setjmp
マクロによって定義された jmp_buf
型の変数を基にジャンプする。
定義
#include <setjmp.h> void longjmp(jmp_buf env, int val);
働き
env がセットされた setjmp
マクロの場所へジャンプする。
このとき、環境はマクロが実行された時と同じになる。ジャンプする先で setjmp
が実行されなかった場合、
または longjump()
が呼び出される前にジャンプする先の関数が実行を終了していた場合、動作は未定義である。
setjmp
マクロがある関数内の自動記憶域変数で volatile 指定がなく内容が変更されたものの内容が未定義であることを除き、全ての参照可能な変数の内容は longjmp
が呼ばれたときの値のままである。
通常の関数呼び出しと return を使わないため、 longjmp()
は割り込み中でも正しく実行される。ただし、多重のシグナルハンドラ(あるシグナルの処理中に別のシグナルが入ったとき)の中で実行された時の動作は未定義である。
返り値
longjmp が完了すると、対応する setjmp
が val の値を返したかのようにプログラムは続行する。
longjmp
関数は setjmp
に 0 を返させることはできない。もし val の値が 0 ならば、 setjmp
は 1 を返す。
解説
定義の最初の段落は、呼び出し元の関数にしかジャンプできないと言っている。つまり、スタックをさかのぼる事はできても、降りることはできない。
2番目の段落は、自動変数がスタックではなくレジスタにあるかもしれないので、 setjmp 後に自動変数の値を変更したときに、 longjmp したら setjmp 時の値に戻ってしまうかもしれないという意味である。 volatile 指定をした自動変数や、静的変数や、ヒープ領域は、 longjmp によって setjmp 時の値に戻ってしまうということはない。
引数の val で返り値をコントロールすれば、理論的には C++ でいう例外処理を実装することができる。大変だろうけど。