setjmp関数とlongjmp関数を使うと、別の関数に制御を移すことが出来ます。ただし、これらの関数を使うと理解しづらく、保守しにくいものになりますので、別の方法があるなら、そちらを使った方がよいでしょう。
#include <setjmp.h>
void longjmp(jmp_buf env, int val);
int setjmp(jmp_buf env);
envはスタックコンテキスト/スタック環境を保存する領域を指定します。
valはlongjmp関数経由でsetjmp関数が実行された場合の戻り値を指定します。
setjmp関数は直接実行された場合は、戻り値として0を返し、longjmp関数経由で実行された場合は、longjmp関数の第2引数の値を返します。
longjmp関数を実行すると、envを使ってスタックコンテキスト/スタック環境を復元して、この環境を作った場所、つまり、setjmp関数実行場所に制御が戻ります。longjmp関数経由で実行されたか否かは、setjmp関数の戻り値で判定します。
プログラム 例
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> jmp_buf env; /* 環境保存 */ int main(void) { /* Input関数の宣言 */ void Input(void); if (setjmp(env) == 0) { /* setjmp自身による実行 */ printf('環境を保存しました\n'); } else { /* longjmpによる実行 */ printf('すぐに終了します\n'); exit(EXIT_FAILURE); } Input(); printf('正常終了です\n'); return EXIT_SUCCESS; } void Input(void) { int in_data; do { printf('10以下の整数を入力してください(0で終了)==> '); scanf('%d', &in_data); if (in_data > 10) { /* main関数のsetjmp実行部分にジャンプ */ longjmp(env, 1); } } while(in_data != 0); return; }
例の実行結果
$ ./longjmp.exe 環境を保存しました 10以下の整数を入力してください(0で終了)==> 1 10以下の整数を入力してください(0で終了)==> 2 10以下の整数を入力してください(0で終了)==> 3 10以下の整数を入力してください(0で終了)==> 0 正常終了です $ echo $? 0 $ ./longjump.exe 環境を保存しました 10以下の整数を入力してください(0で終了)==> 1 10以下の整数を入力してください(0で終了)==> 10 10以下の整数を入力してください(0で終了)==> 11 すぐに終了します $ echo $? 1 $