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は例外(エラー)を処理する手段として普通に使われる。