C макросами с открывающими и закрывающими тегами?
Я только начал читать эту статью об обработке исключений в c с использованием setjmp( jmp_buf) и longjmp( jmp_buf, int). Поэтому я в основном строю связанный список, который использует локальные переменные типа xRecord и связывает его со списком. (Пример 2) Работает просто отлично. Но в примере 3 шаги суммируются в макросы (XTRY и XEND). Что меня больше всего раздражает, так это то, что фактическое выражение switch в примере 2 просто "исчезло" в 3.
Пример 2:
#define DIVIDE_BY_ZERO -3
int SomeFunction(int a, int b)
{
if (b == 0) // can't divide by 0
XRaise(DIVIDE_BY_ZERO);
return a / b;
}
void main(void)
{
XRecord XData;
XLinkExceptionRecord(&XData);
switch (setjmp(XData.Context))
{
case 0: // this is the code block
{
int Result = SomeFunction(7, 0);
// continue working with Result
}
break;
case DIVIDE_BY_ZERO:
printf("a division by zero occurred\n");
break;
default:
printf("some other error occurred\n");
break;
case XFINALLY:
printf("cleaning up\n");
}
XUnLinkExceptionRecord(&XData);
}
Пример 3:
void main(void)
{
XTRY
case XCODE: // this is the code block
{
int Result = SomeFunction(7, 0);
// continue working with Result
}
break;
case DIVIDE_BY_ZERO: // handler for a
specific exception
printf("a division by zero occurred\n");
break;
default: // default handler
printf("some other error occurred\n");
break;
case XFINALLY: // finally handler
printf("cleaning up\n");
XEND
}
У меня вопрос, как я могу построить эти "открывающие и закрывающие" макросы?
2 ответа
Если вы сравните два примера и помните, что макросы C - это простые текстовые замены, то, какими должны быть макросы, становится очевидным:
#define XTRY XRecord XData; \
XLinkExceptionRecord(&XData); \
switch (setjmp(XData.Context)) \
{
#define XEND } \
XUnLinkExceptionRecord(&XData);
Обратите внимание на использование \
чтобы макрос мог занимать более одной строки.
Вы также можете открыть макросы и закрыть новую область (добавив {
а также }
), так что последовательное использование нескольких макросов не приводит к ошибке из-за нескольких определений переменной XData
, Вы также можете использовать do / while(0)
трюк, позволяющий размещать эти макросы непосредственно внутри if
, for
и т.д. без проблем.
Не прячьте {}
это только вызывает проблемы. С C99-совместимым компилятором вы можете скрыть локальные переменные и некоторый код, который выполняется до и после блока:
#define MY_BLOCK \
for (int once = 0; once < 1; ++once) \
for (XRecord XData = { 0 }; once < 1; ++once) \
for (XLinkExceptionRecord(&XData); (XUnLinkExceptionRecord(&XData), (once < 1)); ++once) \
switch (setjmp(XData.Context))
Преимущество состоит в том, что вам нужен только один макрос вместо двух, а {}
будет четко указывать объем конструкции, даже для вашего любимого редактора.