跳轉函數
Goto labol;
Labol:
語句中唯一的限制是它只能跳轉到同一個函數中的某個標號處,而不能跳到別的函數中。其中labol : 和switch語句中的case :一樣是標示符,一個語句前可以有多個標示符,就像缺失了break的swith語句。
C中函數setjmp(jmp_buf j)/longjmp(jmp_buf j, int i)可以實現跨函數的跳轉。
1.setjmp(j)設置“jump”點,用正確的程序上下文填充jmp_buf對象j。這個上下文包括程序存放位置、棧和框架指針,其它重要的寄存器和內存數據。當初始化完jump的上下文,setjmp()返回0值。
2. 以後調用longjmp(j,r)的效果就是一個非局部的goto或“長跳轉”到由j描述的上下文處(也就是到那原來設置j的setjmp()處)。當作爲長跳轉的目標而被調用時,setjmp()返回r或1(如果r設爲0的話)。(記住,setjmp()不能在這種情況時返回0。)
通過有兩類返回值,setjmp()讓你知道它正在被怎麼使用。當設置j時,setjmp()如你期望地執行;但當作爲長跳轉的目標時,setjmp()就從外面“喚醒”它的上下文。你可以用longjmp()來終止異常,用setjmp()標記相應的異常處理程序。
#include<setjmp.h>
#include <stdio.h> /*他們的頭文件*/
jmp_buf j;
void raise_exception(void)
{
printf("exception raised\n");
longjmp(j, 1); /* jump to exception handler */
printf("this line should never appear\n");
}
int main(void)
{
if(setjmp(j) == 0)
{
printf("''setjmp'' isinitializing ''j''\n");
raise_exception();
printf("this line should never appear\n");
}
else
{
printf("''setjmp'' was justjumped into\n");
/* this code is the exception handler */
}
return 0;
}
/* When run yields:
''setjmp'' is initializing''j''
exception raised
''setjmp'' was just jumped into */
那個填充jmp_buf的函數不在調用longjmp()之前返回。否則,存儲在jmp_buf中的上下文就有問題了:(還有就是——只能從被調用的函數跳回到它的直接或間接調用者(同時從棧空間彈出一個或多個棧幀),而不能從一個函數跳轉到另一個和它毫不相干的函數中。setjmp/longjmp函數主要也是用於出錯處理,比如函數A調用函數B,函數B調用函數C,如果在C中出現某個錯誤條件,使得函數B和C繼續執行下去都沒有意義了,可以利
用setjmp/longjmp機制快速返回到函數A做出錯處理)
jmp_buf j;
void f(void)
{
setjmp(j);
}
int main(void)
{
f();
longjmp(j, 1); /* logic error */
return 0;
}