C言語入門講座。関数、サンプル集を参考にして、 C言語をマスターしよう。初心者から上級者まで。

別の関数に制御を移す

2012.08.10

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
$

関連記事