C语言相比C++和Java没有提供异常处理机制,比如 try / catch 机制,但是我们可以使用C语言中的 setjmp / longjmp 方法来模拟出一种类似的异常处理机制。
这两个函数定义在 setjmp.h 头文件中, C文档中对于这两个方法的解释如下:
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
setjmp() and longjmp(3) are useful for dealing with errors and interrupts encountered in a low-level subroutine of a program.
setjmp() saves the stack context/environment in env for later use by longjmp(3).
The stack context will be invalidated if the function which called setjmp() returns.
longjmp() restores the environment saved by the last call of setjmp(3) with the corresponding env argument.
After longjmp() is completed, program execution continues as if the corresponding call of setjmp(3) had just returned the value val.
longjmp() cannot cause 0 to be returned. If longjmp() is invoked with a second argument of 0, 1 will be returned instead.
大致的意思是说,第一次调用 setjmp 会返回0 ,程序会记录下当前的位置和调用环境等信息,等程序出错时,我们调用 longjmp, 并设置第二个参数为非0的整数, 这时程序会终止后面的代码,直接跳转到第一次调用 setjmp 的位置,此时setjmp 的返回值不再是0, 而是返回调用 longjmp 设置的第二个参数。下面用一个简单的代码来演示:
#include <stdio.h>
#include <setjmp.h>
#define DIVIDER_CAN_NOT_BE_ZERO 1
jmp_buf env_buf;
//实现简单的除法
float divide(int a, int b)
{
if (b == 0)
{
longjmp(env_buf, DIVIDER_CAN_NOT_BE_ZERO);
}
return (float)a / b;
}
int main()
{
int errnum = setjmp(env_buf);
if (errnum == 0)
{
//正常的逻辑
printf("a / b = %f\n", divide(3, 0));
return 0;
}
else
{
//出错时的逻辑
if (errnum == DIVIDER_CAN_NOT_BE_ZERO)
{
printf("出错啦,除数不能为0\n");
printf("其他的处理...\n");
}
else
{
printf("其他错误...\n");
}
return errnum;
}
}