· goto
· setjmp, longjmp
· try-catch
一、看看基本的使用
1. goto
这个比较简单,比较容易理解,只要设置一个行标就行了:
例子:
int main ()
{
int i = 0, sum;
for (i = 0; i < 100; ++i) {
sum += i;
if (sum > 1000) goto JMP1;
}
JMP1:
printf("%d\n", i);
return 0;
}
{
int i = 0, sum;
for (i = 0; i < 100; ++i) {
sum += i;
if (sum > 1000) goto JMP1;
}
JMP1:
printf("%d\n", i);
return 0;
}
2. setjmp, longjmp
goto用起来是简单,但是存在一个先天缺陷:只能在同一个函数内使用。
有时候我们写一个代码,有两三层的函数嵌套,想要返回的时候就比较囧。
这时候用setjmp和longjmp就很happy。
例子:
#include <setjmp.h>
jmp_buf jmpbuf1;
void bar() {
printf("Hi, I'm bar!\n");
longjmp(jmpbuf1, 1);
}
void foo() {
printf("Hi, I'm foo!\n");
bar();
printf("Should never come here\n");
}
int main ()
{
int i = 0;
i = setjmp(jmpbuf1);
if (i == 0) { //setjmp第一次某个jmp_buf的时候返回0
foo();
}
else { //否则返回longjmp给出的值
printf("i = %d\n", i);
}
return 0;
}
jmp_buf jmpbuf1;
void bar() {
printf("Hi, I'm bar!\n");
longjmp(jmpbuf1, 1);
}
void foo() {
printf("Hi, I'm foo!\n");
bar();
printf("Should never come here\n");
}
int main ()
{
int i = 0;
i = setjmp(jmpbuf1);
if (i == 0) { //setjmp第一次某个jmp_buf的时候返回0
foo();
}
else { //否则返回longjmp给出的值
printf("i = %d\n", i);
}
return 0;
}
输出是:
Hi, I'm foo!
Hi, I'm bar!
i = 1
3. try-catch (在这里算是歪用了,呵呵)
这个是c++提供的语言特性,可以用于捕获throw语句抛出的异常,不仅可以在函数内使用,也可以跨函数~~
例子:
void bar() {
printf("Hi, I'm bar!\n");
throw 1;
}
void foo() {
printf("Hi, I'm foo!\n");
bar();
printf("Should never come here\n");
}
int main ()
{
try{
foo();
}
catch(int i) {
printf("i = %d\n", i);
}
return 0;
}
printf("Hi, I'm bar!\n");
throw 1;
}
void foo() {
printf("Hi, I'm foo!\n");
bar();
printf("Should never come here\n");
}
int main ()
{
try{
foo();
}
catch(int i) {
printf("i = %d\n", i);
}
return 0;
}
输出是:
Hi, I'm foo!
Hi, I'm bar!
i = 1
二、简单对比一下:
· goto,使用简单方便,看起来比其他两个更容易一点(有行标),但是只能在函数内跳转;
· setjmp和longjmp,稍微麻烦点,需要带个参数(jmp_buf,全局变量,或者传参),好处是可以跨函数跳转,且可以根据setjmp的返回值得知从何处跳转。还有一个小缺陷就是,因为需要先执行setjmp以后才可以跳转,所以可以跳转的地方有一定限制,也使得代码看起来有点不够清晰。
· try-catch,C++有C没有,看起来结构比较清晰,不需要带额外的参数,抛出不同的值(和类型)方便判断来源。
三、重点考察一个问题:
如果有一个class,比如
class T
{
public:
~T() { printf("I'm dead >_<\n"); }
};
那么使用goto、setjmp或try-catch的时候是否存在问题?{
public:
~T() { printf("I'm dead >_<\n"); }
};
if (1) {
T t1;
goto JMP1;
}
JMP1: ;
有输出I'm dead >_<T t1;
goto JMP1;
}
JMP1: ;
jmp_buf jmpbuf1;
if (setjmp(jmpbuf1) == 0) {
T t1;
longjmp(jmpbuf1, 1);
}
else {
;
}
无输出if (setjmp(jmpbuf1) == 0) {
T t1;
longjmp(jmpbuf1, 1);
}
else {
;
}
try {
T t1;
throw 1;
}
catch(int i) {
;
}
有输出I'm dead >_<T t1;
throw 1;
}
catch(int i) {
;
}
所以在使用这三个东西的时候,一定要特别注意,建议在C++里头不使用setjmp,以免查错无门...





