Após toda essa discussão sabemos exatamente como alcançar, em C, o comportamento que ocorre com tratamento de exceções em linguagens de alto nível como C++. Porém a viabilidade do uso das técnicas desenvolvidas nesse texto está ameaçada devido a grande quantidade de código repetitivo que se faz necessário. Para contornar esse problema, pode-se utilizar outra grande funcionalidade presente na linguagem, o preprocessador de macros.
Há um padrão simples que ocorre nesses códigos repetitivos e podemos implementar macros que automatizem essa parte do trabalho facilmente. Primeiro, percebemos que um bloco try é composto pela declaração das variáveis jmp_buf e struct _gvalue e pelo bloco if contendo a negação do valor de retorno de uma chamada a função setjmp recebendo como argumento a variável declarada como sendo do tipo jmp_buf:
#define TRY \
{ \
jmp_buf _eb; \
struct _gvalue _ev = {NULL, NULL}; \
struct _gvalue * const _evp = &_ev \
if (!setjmp(_eb)) {
#define CATCH(_type, _value) \
} else if (_ev.name && !strcmp(_ev.name, #_type)) { \
_type _value = *((_type *)(_ev.value));
#define ENDTRY \
} \
if (_ev.value) free(_ev.value); \
}
Para esse conjunto de macros, uma macro THROW adequada seria:
#define THROW(_type, _value) \
{ \
if (_evp) { \
_evp->name = #_type; \
_evp->value = malloc(sizeof(_type)); \
*((_type *)(_evp->value)) = _value; \
} \
longjmp(_eb, 1); \
}
Com essas macros, caso seja feito um pulo para fora de um bloco CATCH, haverá um vazamento de memória. Também, a ordem TRY-CATCH-ENDTRY deve ser preservada, com os blocos CATCH opcionais (apesar de que essa prática não é recomendada).
Para declarar e usar funções que disparam exceções, as macros abaixo seriam necessárias:
#define THROW_ARGS jmp_buf _eb, struct _gvalue *_evp
#define TRY_ARGS _eb, _evp
Com essas macros, pode-se tratar exceções em C da forma a seguir:
#include "cexceptions.h"
#include <stdio.h>
int divide(int a, int b, THROW_ARGS); // throw const char *
int main()
{
TRY
printf("%i\n", divide(1, 0, TRY_ARGS));
CATCH(const char *, stre)
printf("Erro: %s\n", stre);
ENDTRY
return 0;
}
int divide(int a, int b, THROW_ARGS)
{
if (b)
return a / b;
else
THROW(const char *, "Divisão por 0 impossível no conjunto dos números inteiros");
}