非局所分岐 (大域ジャンプ) (Set Jump)
ヘッダ ファイル |
setjmp.h |
---|---|
規格 | ANSI C (C89) / C90 |
概要 | 通常の関数呼出し及び関数からの復帰の規則を回避するため、マクロ setjmp を定義し、更に 1 つの関数及び 1 つの型を宣言する。 |
C 言語での goto は関数内ジャンプ (ローカルジャンプ) なので、標準 Pascal で言う所の大域ジャンプは許可されません。
C
#include <stdio.h>
int a = 0;
void proc(void)
{
a++;
printf("Count: %d\n", a);
if (a > 9)
goto jmp; // NG
}
int main(void)
{
while (1)
proc();
jmp:
return 0;
}
大域ジャンプは Delphi 等の多くの Pascal 処理系で許可されていません。
Pascal/Delphi
program JmpTest(output);
label
99;
var
a: Integer;
procedure proc;
begin
a := a + 1;
writeln('Count: ', a);
if a > 9 then
goto 99; { Standard Pascal: OK }
end; { Delphi : NG }
begin
a := 0;
while True do
proc;
99:
end.
プラグマ
型
名前 | 機能 |
---|---|
jmp_buf | ローカルでないジャンプ (大域ジャンプ) のためのバッファ (処理系定義の構造体型配列)。 |
マクロ
引数付きマクロ
名前 | 機能 |
---|---|
setjmp() | ローカルでないジャンプ (大域ジャンプ) を設定します。 |
関数
名前 | 機能 |
---|---|
longjmp() | ローカルでないジャンプ (大域ジャンプ) を実行します。 |
非局所分岐 (大域ジャンプ) は主に深くネストした関数呼び出しから抜ける目的で使用されます。
if (setjmp(env) == 0) {
// 直接呼び出された時
} else {
// longjmp() が呼び出された時
}
先述のうまく動作しなかったコードを setjmp()
と longjmp()
で書き替えてみました。
#include <stdio.h>
#include <setjmp.h>
int a = 0;
jmp_buf env;
void proc(void)
{
a++;
printf("Count: %d\n", a);
if (a > 9)
longjmp(env, 1);
}
int main(void)
{
if (setjmp(env) == 0) {
while (1)
proc();
}
return 0;
}
資料
- C 言語 / 標準ライブラリ / setjmp.h (Wikibooks)
- z/OS C/C++ ランタイム・ライブラリー・リファレンス setjmp.h — プログラム状態の操作 (IBM)
- C 言語の標準ヘッダ一覧 setjmp.h (C 言語)