C语言异常处理、try Catch简单实现
C语言异常处理、try/catch简单实现
try/catch是一种错误处理机制,c++和object-c里面都有,c里面没有,这里简单在c里面实现一下:
要在c里面实现try/catch,先了解C标准库提供的两个特殊的函数:setjmp() 及 longjmp(),以及jmp_buf 异常结构
1.setjmp()和longjmp() 函数原型:
int _Cdecl setjmp(jmp_buf jmpb);
void _Cdecl longjmp(jmp_buf jmpb, int retval);
其中_Cdecl是指调用约定,jum_buf是一个全局的异常结构类型,setjmp和longjmp是一对函数,setjmp函数的意义为设置跳转点,函数有这样一个特性:第一次调用返回0,用作初始化,第二次返回值是longjmp的入参retval;longjmp功能是跳转回来再执行一次setjmp,此时调用结构必不为0(貌似就算是0也会转换成1)
2.jmp_buf 异常结构
typedef struct
{
unsigned j_sp; // 堆栈指针寄存器
unsigned j_ss; // 堆栈段
unsigned j_flag; // 标志寄存器
unsigned j_cs; // 代码段
unsigned j_ip; // 指令指针寄存器
unsigned j_bp; // 基址指针
unsigned j_di; // 目的指针
unsigned j_es; // 附加段
unsigned j_si; // 源变址
unsigned j_ds; // 数据段
} jmp_buf;
jmp_buf 结构存放了程序当前寄存器的值,以确保使用 longjmp() 后可以跳回到该执行点上继续执行。
通过一段代码,可以理解2个函数的应用:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
jmp_buf jmpbuffer;
void f1(void)
{
longjmp(jmpbuffer,11);
}
void f2(void)
{
longjmp(jmpbuffer,22);
}
int main(void)
{
int i = 0;
i = setjmp(jmpbuffer);
if(i==0)
{
printf("step:0\n");
f1();
printf("step:1\n");
f2();
printf("step:2\n");
}
else
{
switch(i)
{
case 11:
printf("In fun1\n");
break;
case 22:
printf("In fun2\n");
break;
default:
printf("unkown error\n");
break;
}
exit(0);
}
return 1;
}
f5结果如下: step:0 In fun1 请按任意键继续. . . 简单分析一下运行: 1,第一次运行到setjmp时,函数返回0,i=0,程序当前的环境保存给jmpbuffer 2,执行f1,调用longjmp,入参为11,此时跳转回setjmp 3,再次执行setjmp,函数返回11,i=11,跳到else里面,case 11,运行结束
接下来进入正题,c实现try/catch:
#include"stdio.h"
#include"conio.h"
#include"setjmp.h"
jmp_buf Jump_Buffer;
#define mTry if(!(err=setjmp(Jump_Buffer)))
#define mCatch else
#define mThrow(y) longjmp(Jump_Buffer,y);
int err=0;
double Test(double x,double y)
{
if(y==0 || y>=10000)
{
mThrow(y);
}
else
printf("result=%f\n",x/y);
return 0;
}
int main()
{
double yy=0;
printf("%d",(int)yy);
double x,y;
while (1){
mTry{
puts("Input the 2 value:");
scanf("%lf%lf",&x,&y);
Test(x,y);
}
mCatch{
printf("---------------------------input error,err = %d,y = %lf\n",err,y);
}
}
return 0;
}
Test为要运行的函数,返回x/y,当分母=0或分母太大时抛出异常,err保存异常信息 f5结果如下:
0Input the 2 value:
1 2
result=0.500000
Input the 2 value:
2 0
---------------------------input error,err = 1,y = 0.000000
Input the 2 value:
1 444
result=0.002252
Input the 2 value:
1 1000001
---------------------------input error,err = 1000001,y = 1000001.000000
Input the 2 value:
2222222 1
result=2222222.000000
Input the 2 value:
这里可以看到一个细节:我们的err返回的是y的值,当y=0时,讲道理err应该=0,但是由于setjmp第二次运行时不能等于0,所以将值0转为1了
既已览卷至此,何不品评一二: