Dec
28
goto, setjmp/longjmp, try-catch
注:本文只是简单介绍这三个东西并对比一下其功能、差异,不讨论这些东西是否有存在的必要以及优劣。
· goto
· setjmp, longjmp
· try-catch
一、看看基本的使用
1. goto
这个比较简单,比较容易理解,只要设置一个行标就行了:
例子:
2. setjmp, longjmp
goto用起来是简单,但是存在一个先天缺陷:只能在同一个函数内使用。
有时候我们写一个代码,有两三层的函数嵌套,想要返回的时候就比较囧。
这时候用setjmp和longjmp就很happy。
例子:
输出是:
Hi, I'm foo!
Hi, I'm bar!
i = 1
3. try-catch (在这里算是歪用了,呵呵)
这个是c++提供的语言特性,可以用于捕获throw语句抛出的异常,不仅可以在函数内使用,也可以跨函数~~
例子:
输出是:
Hi, I'm foo!
Hi, I'm bar!
i = 1
二、简单对比一下:
· goto,使用简单方便,看起来比其他两个更容易一点(有行标),但是只能在函数内跳转;
· setjmp和longjmp,稍微麻烦点,需要带个参数(jmp_buf,全局变量,或者传参),好处是可以跨函数跳转,且可以根据setjmp的返回值得知从何处跳转。还有一个小缺陷就是,因为需要先执行setjmp以后才可以跳转,所以可以跳转的地方有一定限制,也使得代码看起来有点不够清晰。
· try-catch,C++有C没有,看起来结构比较清晰,不需要带额外的参数,抛出不同的值(和类型)方便判断来源。
三、重点考察一个问题:
如果有一个class,比如
所以在使用这三个东西的时候,一定要特别注意,建议在C++里头不使用setjmp,以免查错无门...
转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php 。
· 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,以免查错无门...
欢迎扫码关注:
转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php 。
realdodo
2009-12-30 13:48
c++的try catch就是用setjmp来实现的,而且try catch就是为了避免调用这几个函数而设计的,因此c++中当然不要使用喽~
felix021 回复于 2009-12-30 14:28
明白了~~
sandy
2009-12-28 22:39
这不是Effective C++(还是C++Primer来着?)被经常拿来对比的例子么。。setjmp/longjmp在大多数情况下会让代码变得极为恐怖。。
felix021 回复于 2009-12-28 22:42
很少看到setjmp的使用。从C++的角度看来,的确不应该用;但是不知道在C项目中用得多不多。
分页: 1/1 1