setjmp, longjmp - 大域ジャンプ

【書式】

#include <setjmp.h>

int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

【解説】

setjmp(), longjmp()は、関数呼び出しが何重にも入れ子になっているとき

に、いっきに上位の関数に戻るときに使います。

まずジャンプ先の場所でsetjmp()を呼んでjmp_buf型変数envにその時点の環

境およびジャンプ先の番地をセーブしておきます。

そして、 ジャンプしたい場所では、 ジャンプ先の環境がセーブされている

env をパラメタとしてlongjmp()を呼びます。この時、valにセットした値が

setjmp()の返す値になります。

longjmp()を通してsetjmp()からリターンしてきた場合、 レジスタ変数の値

は不定となりますので注意してください。LSI C-86ではローカル変数はデフ

ォルトでレジスタ変数となりますので、特に注意が必要です。setjmp()を呼

び出す関数のローカル変数はvolatile指定をして、レジスタ変数とならない

ようにしてください。

【使用例】

jmp_buf env;

int val(char **s)

{

if (! isdigit(**s)) {

fprintf(stderr, "missing number\n");

longjmp(env, 1);

}

return (strtol(*s, s, 10));

}

void bar(char *s)

{

int v;

v = val(&s);

switch (*s++) {

case '+': return (v + val(&s));

case '-': return (v - val(&s));

case '*': return (v * val(&s));

case '/': return (v / val(&s));

default:

fprintf(stderr, "illegal operation\n");

longjmp(env, 1);

}

}

void main()

{

char line[80];

for (;;) {

printf(">");

gets(line);

if (setjmp(env) == 0)

printf("%d\n", bar(line));

}

}

【リターン値】

setjmp() は最初に呼ばれた時は、 値0を返します。longjmp()が呼ばれた時

は、その引数valがsetjmp()の返す値となります。

ただし、longjmp()でvalに0を渡した場合、setjmp()は1を返します。したが

ってsetjmp()の最初の呼び出しとlongjmp() によるリターンとを確実に区別

することができます。

【可搬性】

ANSI, UNIX, DOS窓

【バグ】

setjmp(), longjmp()は使い方を誤ると危険ですので、次の2点に注意してく

ださい。

+ setjmp()を呼ぶ関数は必ずレジスタ割り付けをしないことを指定してく

ださい

+ setjmp()を呼んでいる関数がreturnした後にlongjmp()を呼ぶと、プロ

グラムは暴走してしまいますので絶対に呼ばないでください

【copyright (c) 安江正樹@東海大学理学部物理学科】