longjmp()は、setjmp()した場所へ跳ぶC言語の関数。
|
longjmp()は、関数をまたいで跳べるgotoのようなもの(ただし“元の場所”へ戻ることしか出来ない)。
C++やJavaのthrow-catchに近い。
#include <stdio.h> #include <setjmp.h>
jmp_buf jmpbuf1; void sub(void) { printf("sub start\n"); longjmp(jmpbuf1, 123); printf("sub end\n"); } int main() { printf("main start\n"); int c = setjmp(jmpbuf1); if (c == 0) { // 最初にここが実行される sub(); } else { // longjmp()が呼ばれると、ここに来る printf("jump: %d\n", c); } printf("main end\n"); }
ジャンプ情報を保持する為にjmp_bufの変数を用意する。
setjmp()で、戻ってくる場所を指定する。
最初はsetjmp()は0を返すので、後続処理を記述する。
後続処理がlongjmp()を呼び出すと、setjmp()に戻ってきて、0以外を返す。この値はlongjmp()の第2引数で指定した値になる(0を指定すると1が返ってくる)。
(「longjmp()を必ず呼ばなければならない」という事は無いし、jmp_bufをクリアする必要も無い)
setjmp/longjmpはC++やJavaのtry-catch/throwに似ている。
C言語 | Java |
---|---|
jmp_buf jmpbuf1; |
class MyException extends RuntimeException{} |
void sub(void) { longjmp(jmpbuf1); } |
static void sub() { throw new MyException(); } |
int main() { int c = setjmp(jmpbuf1); if (c == 0) { sub(); } else { printf("jump\n"); } } |
public static void main(String[] args) { try { sub(); } catch(MyException e) { System.out.println("jump"); } } |
※setjmp/longjmpがある意味禁じ手・奥の手であるのに対し、Javaのthrow/catchは例外(エラー)を処理する手段として普通に使われる。