用C语言实现try cash --《Implementing Exceptions in C》

 Exceptions.h文件源码

/* Copyright 1989 Digital Equipment Corporation.                          */
/* Distributed only by permission.                                        */
/**************************************************************************/
/* File: exception.h                                                      */
/* Last modified on Wed Mar 15 16:40:41 PST 1989 by roberts               */
/*                                                                        */
/* The exception package provides a general exception handling mechanism  */
/* for use with C that is portable across a variety of compilers and      */
/* operating systems. The design of this facility is based on the         */
/* exception handling mechanism used in the Modula-2+ language at DEC/SRC */
/* and is described in detail in the paper in the documents directory.    */
/* For more background on the underlying motivation for this design, see  */
/* SRC Research Report #3.                                                */
/**************************************************************************/

#include <setjmp.h>
#include <stdlib.h>

#define MaxExceptionsPerScope 10
#define ETooManyExceptClauses 101
#define EUnhandledException   102

#define ES_Initialize 0
#define ES_EvalBody   1
#define ES_Exception  2

typedef struct { char *name ;} exception;

typedef struct _ctx_block {
    jmp_buf jmp;
    int nx;
    exception *array[MaxExceptionsPerScope];
    exception *id;
    int value;
    int finally;
    struct _ctx_block *link;
} context_block;

extern exception ANY;
extern context_block *exceptionStack;
extern void _RaiseException(exception *e, int v);

#define RAISE(e, v) _RaiseException(&e, v)

#define TRY \
    {\
        context_block _ctx;\
        int _es = ES_Initialize;\
        _ctx.nx = 0;\
        _ctx.link= NULL;\
        _ctx.finally = 0;\
        _ctx.link = exceptionStack;\
        exceptionStack = &_ctx;\
        if (setjmp(_ctx.jmp) != 0) _es = ES_Exception;\
        while (1) {\
            if (_es == ES_EvalBody) {
              
#define EXCEPT(e) \
                if(_es == ES_EvalBody)  exceptionStack = _ctx.link;\
                break;\
            }\
            if (_es == ES_Initialize) {\
                if (_ctx.nx >= MaxExceptionsPerScope)\
                    exit(ETooManyExceptClauses);\
                _ctx.array[_ctx.nx++] = &e;\
            } else if (_ctx.id == &e || &e == &ANY) {\
                int exception_value = _ctx.value;\
                exceptionStack = _ctx.link;

#define FINALLY \
            }\
            if (_es == ES_Initialize) {\
                if (_ctx.nx >= MaxExceptionsPerScope)\
                    exit(ETooManyExceptClauses);\
                _ctx.finally = 1;\
            } else {\
                exceptionStack = _ctx.link;
                
#define ENDTRY \
                if (_ctx.finally && _es == ES_Exception)\
                    _RaiseException(_ctx.id, _ctx.value);\
                break;\
            }\
            _es = ES_EvalBody;\
        }\
    }

  Exceptions.c文件源码

/* Copyright 1989 Digital Equipment Corporation.                          */
/* Distributed only by permission.                                        */
/**************************************************************************/
/* File: exception.h                                                      */
/* Last modified on Wed Mar 15 16:40:42 PST 1989 by roberts               */
/*                                                                        */
/* Implementation of the C exception handler. Much of the real work is    */
/* done in the exception.h header file.                                   */
/**************************************************************************/

#include <stdio.h>
#include "exception.h"

context_block *exceptionStack = NULL;

exception ANY;

void _RaiseException(exception *e, int v){
    context_block *cb, *xb;
    exception *t;
    int i, found;

    found = 0;
    for (xb = exceptionStack; xb != NULL; xb = xb->link) {
        for (i = 0; i < xb->nx; i++) {
            t = xb->array[i];
            if (t == e || t == &ANY) {
                found = 1;
                break;
            }
        }
        if (found) break;
    }
    if (xb == NULL) exit(EUnhandledException);
    for (cb = exceptionStack; cb != xb && !cb->finally; cb = cb->link);
    exceptionStack = cb;
    cb->id = e;
    cb->value = v;
    longjmp(cb->jmp, ES_Exception);
}

 test.c测试函数

#include "exception.h"
#include <stdio.h>

exception e = { "假装是个很严重的错误"};
void raiseE(exception *toRaise){
  RAISE(*toRaise,100);
}

void main(){
  int i = 0;
  TRY
    TRY
      ++i;
	  if(a == NULL)
		raiseE(&e);
      --i;
    FINALLY
      printf("FINAL\n");
    ENDTRY
  EXCEPT(e)
    printf("捕获到异常e:%s;异常码:%d\n",e.name,exception_value);
  ENDTRY
    printf("i = %d\n",i);
    system("pause");
}

 异常可以从函数内部的抛出,并且跳过了–i这一句,所以最终i的值为1,并且运行了FINALLY语句块后继续抛出,并被EXCEPT(e)语句块捕获,然后成功获得了异常信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值