让宏定义返回函数的值是不好的做法吗?
Is it bad practice to have a macro definition return a value for a function?
使用定义为有条件返回值的宏有一个缺点,即仅从查看客户端代码时无法看出可能在宏的位置退出。
我正在考虑的用例是编写一个值和错误检查,如下所示:
#define WRITE_CHK(file, param)
if (!write_that_returns_zero_on_fail(file, param)) {
handle_error();
return false;
}
客户机代码:bool myfunc()
{
...
WRITE_CHK(file, param) // function might return here
...
return true;
}
我很好奇这个宏的好处(它将在我的代码中的许多地方使用)是否会超过上面提到的缺点。除了简单地展开(不使用宏)之外,是否有更好的替代方案?
标准答案是"不要使用宏";但这通常有点过于简单化了。在某些情况下,它们可以大大减少冗长的样板文件。
那么,为什么不将事实编码到宏名称中呢?例:WRITE_OR_RETURN_ON_FAILURE
;它可能有点冗长,但它不太可能使代码的读者出错。
在宏中隐藏控制流并不常用,因此对于必须理解或调试代码的开发人员来说,这可能会使他们感到困惑。
我建议完全不要使用宏,但如果必须使用宏,请确保控制流部分是显式的。
// assume handle_error returns true
#define WRITE_FAILED(file, param)
(!write_that_returns_zero_on_fail(file, param) && handle_error())
// macro usage
if(WRITE_FAILED(file, param))
{
return;
}
另一个要问自己的问题是——你为什么要在这里使用宏呢?如果要隐藏控制流,那就不是个好主意。还有别的原因吗?
创建两步宏:
#define WRITE_CHK_(file, param, HANDLER)
if (!write_that_returns_zero_on_fail(file, param)) {
handle_error();
HANDLER
}
#define RFALSE return false;
#define WRITE_CHK(file, param) WRITE_CHK_(file, param, RFALSE)
如果您需要在其他地方进行类似的检查(或直接使用WRITE_CHK(file, param, return false)
),则可以制作其他包装器
是的,很糟糕。使用goto
#define fail_unless(x) do {if(!(x)) goto fail;} while (0)
int foo()
{
fail_unless( my_write(...) );
fail_unless( bar() );
return 0;
fail:
cleanup();
return -1;
}
Edit:如果你因为不明白while循环在那里做什么而投票,你应该问一下。这是确保C宏在任何上下文中都充当单个语句的标准技术。如果你的宏展开为If语句(就像其他的宏一样),那么你会得到意想不到的副作用,例如:
#define DONT_DO_THIS(x) if (!x) { foo; }
if (a) DONT_DO_THIS(x)
else something_else();
您期望在!a
时执行something_else,但宏实际上扩展为:
if (a)
if (!x) { foo;}
else something_else();
something_else在a && x
时执行,而不是在!a
时执行。
相关文章:
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- C++宏定义和取消定义
- 如何在C++中允许成员函数的自定义返回类型进行类型擦除?
- 如何在 Cython 中定义返回 cpp 定义类型的函数?
- 根据 c++ 标准在该宏定义中推送/弹出宏时的行为是什么
- VS2017 #error: : snprintf 的宏定义与标准库函数声明冲突
- 宏定义不正确没有错误
- Visual Studio:snprintf 冲突的宏定义
- 宏定义中的预处理器令牌两边有两个双引号
- CMake 添加和删除宏定义以编译共享库/可执行文件
- 宏C++#定义示例(对象)(::f(s,(对象),arg1,arg2,arg3)
- 根据模板参数选择宏定义
- 使用宏定义打印格式参数
- 我应该如何定义返回指针的函数?(引用指针与指针指针)
- 组合宏定义以一次获得多个定义 [avr C++]
- 如何在可执行文件中查看宏定义值
- 是否有另一种方法可以在不使用宏定义的情况下进行此操作
- 如何理解宏定义
- 如何在C++中定义宏函数返回void或else
- 让宏定义返回函数的值是不好的做法吗?