S-JIS[2012-11-23]

setjmp/longjmp関数

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をクリアする必要も無い)


throw-catchとの対比

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


C言語目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま