setjmp&longjmp

setjmpとlongjmpが関数をまたいだgotoを実現するってのは概念的にはわかってたんだけど、実際どういうふうに使うのかわからなかったので試してみた。何で急にこんなことをしたのかと言うと、Super Technique 講座〜longjmpと例外をひょんなことから見つけて読んで、気になったので。
setjmp・longjmpは例外処理に使われる場合が多いってことで、勝手にCでは例外処理をこんな感じで実装するんだと考えて書いてみた。

#include <stdio.h>
#include <setjmp.h>

jmp_buf jbuf;

void exception_handler(char *msg) {
  fprintf(stderr, "%s", msg);
  longjmp(jbuf, 1);
}

int main() {
  printf("setjump & longjump test\n");

  if (setjmp(jbuf) == 0) {
    if (1) {
      exception_handler("something works wrong!\n");
    }
  } else {
    printf("handling exception\n");
  }
  return 0;
}

上のリンク先のページだと、setjmpを実行してるif節の行がJavaで言うtryで、"} else {"がcatch、exception_handlerの呼び出しが"throw new Exception()"に該当するらしい。
最初、このコードを書いただけでは、何でこんな処理でsetjmp・longjmpが必要なんだろう?って疑問に思っちゃったけど、longjmpの呼び出しが、setjmpブロック内で呼び出している関数内の深いところで行われているのなら、十分有用だね。

jmp_buf jbuf;

void sub2() {
  fprintf(stderr, "in sub2\n");
  longjmp(jbuf, 1);
}

void sub1() {
  fprintf(stderr, "in sub1\n");
  sub2();
}

int main() {
  printf("setjump & longjump test\n");

  if (setjmp(jbuf) == 0) {
    sub1();
  } else {
    printf("jumped from sub2\n");
  }
  return 0;
}

例外処理以外ではどんなところに使われているんだろう?後で暇があったら調べてみる。