1

我刚开始阅读这篇关于在 c 中使用 setjmp( jmp_buf ) 和 longjmp( jmp_buf, int ) 处理异常的文章。因此,我基本上构建了使用 xRecord 类型的局部变量的链接列表并将其链接到列表。(示例2)它工作得很好。但在示例 3 中,这些步骤被总结为宏(XTRY 和 XEND)。最让我恼火的是,示例 2 的实际 switch 语句只是在 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
   }

我的问题是,如何构建这些“打开和关闭”宏?

4

2 回答 2

1

如果您比较这两个示例,并记住 C 宏是简单的文本替换,那么宏应该是什么是显而易见的:

#define XTRY  XRecord XData; \
              XLinkExceptionRecord(&XData); \
              switch (setjmp(XData.Context)) \
              {

#define XEND  } \
              XUnLinkExceptionRecord(&XData);

请注意使用\允许宏跨越多行。

您可能还希望宏打开和关闭一个新范围(通过添加{and }),以便连续使用多个宏不会由于变量的多个定义而产生错误XData。您还可以使用该do / while(0)技巧允许将这些宏直接放置在if,for等内部而不会出现问题。

于 2012-09-09T15:38:57.023 回答
1

不要隐藏{}这只会造成麻烦。使用符合 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))

好处是您只需要一个宏而不是两个,并且{}可以清楚地指示构造的范围,即使对于您最喜欢的编辑器也是如此。

于 2012-09-09T16:01:01.630 回答