我刚开始阅读this article关于使用setjmp(jmp_buf)和longjmp(jmp_buf,int)的c中的异常处理。所以我基本上构建了使用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
}
我的问题是,如何构建这些“打开和关闭”宏?
答案 0 :(得分:1)
如果比较这两个例子,并记住C宏是简单的文本替换,那么宏应该是显而易见的:
#define XTRY XRecord XData; \
XLinkExceptionRecord(&XData); \
switch (setjmp(XData.Context)) \
{
#define XEND } \
XUnLinkExceptionRecord(&XData);
请注意使用\
来允许宏跨越多行。
您可能还希望让宏打开并关闭新范围(通过添加{
和}
),以便连续使用多个宏不会因多个错误而产生错误变量XData
的定义。您还可以使用do / while(0)
trick将这些宏直接放在if
,for
等内,而不会出现问题。
答案 1 :(得分: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))
好处是你只需要一个宏而不是两个,而{}
将清楚地表明构造的范围,即使对于你最喜欢的编辑也是如此。