【发布时间】:2019-09-08 17:46:25
【问题描述】:
是否可以创建一个扩展以下代码的宏
int error = 0;
struct parse_tree res = CLEANUP_parse(file_hdl);
// ...
cleanup:
return error
变成语义上等价(足够)的东西
int error = 0;
struct parse_tree res;
struct parse_tree tmp = parse(file_hdl);
if(global_error_variable != 0) {
error = global_error_variable;
goto cleanup;
} else {
res = tmp;
}
// ...
cleanup:
return error
我担心这是不可能的原因是goto label; 是一个语句,我真的需要一个表达式。例如。像
#define CLEANUP_parse(file_hdl) ((tmp=parse(file_hdl)) ^ tmp ^ global_error_variable) ? goto cleanup : tmp
因为这个原因不起作用(并且因为 tmp 没有声明,可能还有更多)。
不幸的是,编译器扩展只有在 GCC、VSC 和德州仪器的 C 编译器支持时才有可能。
背景
我们有一个现有的代码库,其中每个函数返回一个整数错误代码,调用者在非零返回代码上跳转到cleanup:。我考虑引入使用全局错误代码来启用其返回值的函数,但希望以安全和向后兼容的方式这样做。 The full picture on SE Code Review
【问题讨论】:
-
编译器扩展是否满足您的需要?
-
@StoryTeller:很可能不会:它需要与 GCC、VSC 和德州仪器 C 编译器一起运行。
-
您通常可以使用宏创建
try/catch/finally功能,这些宏在底层使用丑陋的setjmp/longjmp魔法(例如something like this probably,未经测试)。 This thread 做了类似的事情。在 MSVC 中,您将使用__try和__finally,这显然是不可移植的。 -
另外,调用一个名为
division的函数会改变一个global_error_variable是你更大的问题。我将首先重新设计您的程序以避免访问全局状态,并避免创建会使代码维护者生气的宏。 -
@Groo:我选择
division是为了有一个可能失败的简单示例(除以零),但实际上这些函数并不纯粹,并且包含“文件打开错误”中的所有内容以“内存分配失败”作为可能的错误条件。我正在调查setjmp/longjmp。
标签: c macros c-preprocessor