スポンサーリンク

setjmp / longjmp

setjmp , longjmp

C言語のsetjmpとlongjmpについて。

libpngのサンプルでsetjmpが出てきてびっくりしたので挙動の確認をしておきたい。

setjmp /longjmp はセットで使う。


1.setjmpを一回呼び出すと、必ず0を返して戻ってくる。

2.その後、longjmpを呼び出すと、先ほどsetjmpが呼ばれた文まで戻り、再びsetjmpが呼ばれる。

3.その時のsetjmpの戻り値は、先に呼び出したlongjmpの第二引数となる


これだけだとgotoと似たようなものに思えるが、setjmpに対するlongjmpの呼び出しは、別の関数の中でもかまわない。関数を飛び越えて戻ってくる。


例1

動作

コード

#include <csetjmp>

std::jmp_buf jmp_bf; int main() { int a = 3; int b = 0; if (setjmp(jmp_bf) == 0) { if (b == 0) { longjmp(jmp_bf, 1); } int c = a / b; printf("%d / %d = %d", a, b, c); } else { printf("0 divide error.\n"); } }

C言語には例外(try…catch…)がない。この、「関数を飛び越えて戻ってくる」という特性を生かして、C言語で例外処理に近いことができる。

つまり、以下のC++コードに近いことができる。

例2 関数間ジャンプ

C++例外使用版

int main()
{

  int a = 3;
  int b = 0;


  try{

    int c = a / b;
    printf("%d / %d = %d", a, b, c);

  }
  catch(...) {

    std::cout << "0 divide error";

  }



  std::cout << "Hello World!\n";
}

setjmp使用版

#include <iostream>

#include <csetjmp>

std::jmp_buf jmp_bf;
int divide(int a, int b) {

  if (b == 0) {
    longjmp(jmp_bf, 1);//mainのsetjmpまで飛ぶ
  }

  return a / b;
}
int main()
{

  int a = 3;
  int b = 0;

//初回は0
//longjmp後は1
 if (setjmp(jmp_bf) == 0) { int c = divide(a,b); printf("%d / %d = %d", a, b, c); } else { printf("0 divide error.\n"); } }

動作

libpngを試す(CMakeビルド)

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: