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))

Преимущество состоит в том, что вам нужен только один макрос вместо двух, а {} будет четко указывать объем конструкции, даже для вашего любимого редактора.

Другие вопросы по тегам