return 函数结果的 C 宏 if != 0
C macros to return function result if != 0
我有一个调用其他函数的 C 函数,每个函数 returns int
,其中 0
正常,如果 != 0 则为错误代码。该函数如下所示:
int myfunc()
{
int err;
err = func1(arg1);
if (err != 0) {
return err;
}
err = func2(arg2, arg3);
if (err != 0) {
return err;
}
err = func3(arg4, arg5);
if (err != 0) {
return err;
}
err = func4();
if (err != 0) {
return err;
}
return 0;
}
如您所见,我有很多样板代码:
err = some_func();
if (err != 0) {
return err;
}
能不能写个宏来简化一下?类似于:
#define TRY() ???
int myfunc()
{
TRY(func1(arg1));
TRY(func2(arg2, arg3));
TRY(func3(arg4, arg5));
TRY(func4());
}
#define TRY(expression) \
do { \
int err = (expression); \
if (err != 0) { \
return err; \
} \
} while (0)
这使 err
范围限于宏。如果变量名位于单独的花括号块中,则每次使用相同的变量名是合法的。
底部仍然需要 return 0
。
int myfunc()
{
TRY(func1(arg1));
TRY(func2(arg2, arg3));
TRY(func3(arg4, arg5));
TRY(func4());
return 0;
}
另请参阅:
- do { … } while (0) — what is it good for?
- Why do multi-line macros have backslashes at the end of each line?
我会说你已经拥有的已经很好了。是的,它是重复的,但仍然很容易阅读。隐藏跳转语句,如 return
,在宏后面几乎不是一个好主意。
如果您坚持要缩短它,您可以使用逻辑 AND 或 OR 运算符链接函数调用:
if((err = func1(arg1)) != 0 ||
(err = func2(arg2, arg3)) != 0 ||
(err = func3(arg4, arg5)) != 0 ||
(err = func4()) != 0)
{
return err;
}
之所以可行,是因为逻辑运算符具有短路行为。当第一个或条件为真时,不评估或执行其余条件。
如果出于某种原因,例如代码指南,您不能在 if
语句条件中进行赋值,您可以将代码链移至其上方:
(err = func1(arg1)) != 0 ||
(err = func2(arg2, arg3)) != 0 ||
(err = func3(arg4, arg5)) != 0 ||
(err = func4()) != 0;
if(err != 0) {
return err;
}
由于 if 语句唯一的作用是 return 错误代码,因此可以通过删除所有 if 语句并在函数末尾只有一个 return 语句来进一步简化。 (感谢 Jonathan Leiffer)
(err = func1(arg1)) != 0 ||
(err = func2(arg2, arg3)) != 0 ||
(err = func3(arg4, arg5)) != 0 ||
(err = func4()) != 0;
return err; /* Returns error code or 0. */
我有一个调用其他函数的 C 函数,每个函数 returns int
,其中 0
正常,如果 != 0 则为错误代码。该函数如下所示:
int myfunc()
{
int err;
err = func1(arg1);
if (err != 0) {
return err;
}
err = func2(arg2, arg3);
if (err != 0) {
return err;
}
err = func3(arg4, arg5);
if (err != 0) {
return err;
}
err = func4();
if (err != 0) {
return err;
}
return 0;
}
如您所见,我有很多样板代码:
err = some_func();
if (err != 0) {
return err;
}
能不能写个宏来简化一下?类似于:
#define TRY() ???
int myfunc()
{
TRY(func1(arg1));
TRY(func2(arg2, arg3));
TRY(func3(arg4, arg5));
TRY(func4());
}
#define TRY(expression) \
do { \
int err = (expression); \
if (err != 0) { \
return err; \
} \
} while (0)
这使 err
范围限于宏。如果变量名位于单独的花括号块中,则每次使用相同的变量名是合法的。
底部仍然需要 return 0
。
int myfunc()
{
TRY(func1(arg1));
TRY(func2(arg2, arg3));
TRY(func3(arg4, arg5));
TRY(func4());
return 0;
}
另请参阅:
- do { … } while (0) — what is it good for?
- Why do multi-line macros have backslashes at the end of each line?
我会说你已经拥有的已经很好了。是的,它是重复的,但仍然很容易阅读。隐藏跳转语句,如 return
,在宏后面几乎不是一个好主意。
如果您坚持要缩短它,您可以使用逻辑 AND 或 OR 运算符链接函数调用:
if((err = func1(arg1)) != 0 ||
(err = func2(arg2, arg3)) != 0 ||
(err = func3(arg4, arg5)) != 0 ||
(err = func4()) != 0)
{
return err;
}
之所以可行,是因为逻辑运算符具有短路行为。当第一个或条件为真时,不评估或执行其余条件。
如果出于某种原因,例如代码指南,您不能在 if
语句条件中进行赋值,您可以将代码链移至其上方:
(err = func1(arg1)) != 0 ||
(err = func2(arg2, arg3)) != 0 ||
(err = func3(arg4, arg5)) != 0 ||
(err = func4()) != 0;
if(err != 0) {
return err;
}
由于 if 语句唯一的作用是 return 错误代码,因此可以通过删除所有 if 语句并在函数末尾只有一个 return 语句来进一步简化。 (感谢 Jonathan Leiffer)
(err = func1(arg1)) != 0 ||
(err = func2(arg2, arg3)) != 0 ||
(err = func3(arg4, arg5)) != 0 ||
(err = func4()) != 0;
return err; /* Returns error code or 0. */