Thinking——C 模拟 Exception

本贴最后更新于 2121 天前,其中的信息可能已经时移世改

异常处理

C 中没有 exception,所以我们可以用函数返回值来判断错误类型。但有时候又希望在顶层能统一处理错误,让代码更简洁一点。其实第一个想到的可能是 goto 语句,但是 goto 不能跳转到另一个函数的某个 label,不过 C 提供了另外两个函数来完成这个任务:setjmplongjmp

函数原型

#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);

例子

第一次调用 setjmp 会返回 0,并且将函数在此处的上下文保存在 jmp_buf 结构体里。调用 longjmp 函数时,jmp_buf 从 setjmp 函数保存的上下文恢复,然后程序跳转到 setjmp 处,setjmp 再次返回,如果 longjmp 设置的 val 为 0,则 setjmp 返回 1,否则返回 val。

#include <stdio.h>      /* printf, scanf */
#include <stdlib.h>     /* exit */
#include <setjmp.h>     /* jmp_buf, setjmp, longjmp */

main()
{
  jmp_buf env;
  int val;

  val = setjmp (env);
  if (val) {
    fprintf (stderr,"Error %d happened",val);
    exit (val);
  }

  /* code here */

  longjmp (env,101);   /* signaling an error */

  return 0;
}

C 中的宏

宏(macro)就是用 #define 定义的一个符号,在编译预处理时,对程序中所有出现的“宏名”,都会被宏定义时的字符串所替换。一般形式:

#define 宏名 字符串

宏可以分为两类:有参数和无参数。

// 无参数
#define PI 3.1415926

// 有参数
#define MULTIPLY(x, y) (x) * (y)

宏用的好,可以让 C 程序简洁合理很多。

实现 Exception

#include <stdio.h>
#include <setjmp.h>

static jmp_buf ex_buf__;

#define TRY switch(setjmp(ex_buf__)) { case 0:
#define CATCH(x) break; case x:
#define ETRY break; }
#define THROW(x) longjmp(ex_buf__, x)

#define FOO_EXCEPTION (1)
#define BAR_EXCEPTION (2)
#define BAZ_EXCEPTION (3)

void dosomething()
{
	printf("I am doing something!\n");
	THROW( BAR_EXCEPTION );
	printf("I am not reachable\n");
}

int main(int argc, char** argv)
{
	TRY 
	{
		dosomething();
	}
	CATCH( FOO_EXCEPTION )
	{
	   printf("Got Foo!\n");
	}
	CATCH( BAR_EXCEPTION )
	{
	   printf("Got Bar!\n");
	}
	CATCH( BAZ_EXCEPTION )
	{
	   printf("Got Baz!\n");
	}
	ETRY;
	printf("everything ends\n");
	return 0;
}
打赏 20 积分后可见
20 积分
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    106 引用 • 152 回帖 • 2 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    83 引用 • 165 回帖 • 47 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    915 引用 • 931 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 88250

    (应该发问答帖的)

    1 回复
  • salamander
    作者

    好的,不好意思

    1 回复
  • 88250

    没有啦,是设计不合理导致误用,等我们再调整下 😂