Aus*_*ser 5 c error-handling gcc c-preprocessor
我经常编写代码,这些代码最终都是长序列
int error;
error = do_something();
if (error) {
return error;
}
error = do_something_else(with, some, args);
if (error) {
return error;
}
error = do_something_yet_again();
if (error) {
return error;
}
return 0;
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种更清晰的方式来写这个,这在某种程度上避免了重复的相同检查.到目前为止,我已经编写了一个ERROR_OR宏,它的工作方式类似于
#define ERROR_OR(origerr, newerr) \
({ \
int __error_or_origerr = (origerr); \
(__error_or_origerr != 0) \
? __error_or_origerr \
: (newerr); \
})
Run Code Online (Sandbox Code Playgroud)
这允许原始代码变得像
int error = 0;
error = ERROR_OR(error, do_something());
error = ERROR_OR(error, do_something_else(with, some, args));
error = ERROR_OR(error, do_something_yet_again());
return error;
Run Code Online (Sandbox Code Playgroud)
这(在我看来)有点清洁.它也不太容易理解,因为ERROR_PRESERVE除非你阅读它的文档和/或实现,否则宏的功能并不明显.它也没有解决重复的问题,只是更容易在一行上编写所有(现在隐式)检查.
我真的想重写这一切,如下所示:
return ERROR_SHORT_CIRCUIT(
do_something(),
do_something_else(with, some, args),
do_something_yet_again()
);
Run Code Online (Sandbox Code Playgroud)
假设的ERROR_SHORT_CIRCUIT宏会
最后一个条件是我的短路偏离了||操作员的直接使用- 因为这将评估为1而不是误差值.
我最初尝试写这个是以下内容:
#define ERROR_SHORT_CIRCUIT(firsterr, ...) \
({ \
int __error_ss_firsterr = (firsterr); \
(__error_ss_firsterr != ERROR_NONE) \
? __error_ss_firsterr \
: ERROR_SHORT_CIRCUIT(__VA_ARGS__); \
})
Run Code Online (Sandbox Code Playgroud)
这有两个明显的问题:
__VA_ARGS__是单个值时)我已经研究了一些递归的宏观黑客攻击,但我不喜欢使用那种程度的预处理器魔法 - 太多的空间让某些东西变得微不足道.我也考虑使用真实的(可能是可变的)函数,但这也需要
并且这两者似乎都比原始的显式代码更糟糕.
我很想听听有关处理此问题的最佳方法的建议.我对许多不同的方法持开放态度,但我的最终目标是在不损害可读性的情况下避免重复.
(我想很明显我在||Ruby这样的语言中对操作符的行为感到嫉妒).
我会使用如下代码:
if ((error = do_something()) != 0 ||
(error = do_something_else(with, some, args)) != 0 ||
(error = do_something_yet_again()) != 0)
return error;
return 0;
Run Code Online (Sandbox Code Playgroud)
它是完全定义的,因为每个运算符之前都有序列点||。它实际上不需要宏。仅当您在函数调用之间分配资源或执行其他操作时,它才会遇到问题,但这与示例代码显示的不同。至少 90% 的战斗是创建do_something_or_other()函数序列,以便轻松处理错误排序。