C 中的大小写可变宏

Bre*_*men 2 c macros variadic-macros c11

我有 2 个包装宏用于断言函数输入参数:

/**
 * @brief   An assert wrapper with no value return in case assert fails.
 * @param   x_: value to test for being non zero.
 */
#define UTIL_ASSERT_VOID(x_)                                                \
    assert_param(x_);                                                       \
    if (!x_)                                                                \
        return;                                                             \

/**
 * @brief   An assert wrapper with a value return in case assert fails.
 * @param   x_: value to test for being non zero.
 */
#define UTIL_ASSERT_VAL(x_, ret_)                                           \
    assert_param(x_);                                                       \
    if (!x_)                                                                \
        return ret_;                                                        \
Run Code Online (Sandbox Code Playgroud)

前者用于返回 void 的函数,后者用于返回非 void 的函数。我想知道在 C11(或更早版本)中有一种机制允许一个人只使用一个带有可变参数数量的宏。根据提供给宏的参数数量(1 或 2),a returnorreturn ret_将被编译。

Afs*_*hin 5

你可以这样做:

#define UTIL_ASSERT(x_, ...)                                                \
    assert_param(x_);                                                       \
    if (!x_)                                                                \
        return __VA_ARGS__;
Run Code Online (Sandbox Code Playgroud)

但是请记住,您不能保证在这个可变参数宏中只有 1 个参数,因此您需要正确使用它。

更新: 多亏了这个线程,我找到了更好的方法:

void assert_param(int x);

#define UTIL_ASSERT_1(x_)   do { assert_param(x_); if (!x_) return; } while(0)

#define UTIL_ASSERT_2(x_, ret_)   do { assert_param(x_); if (!x_) return ret_; } while(0)     

#define GET_MACRO(_1,_2,NAME,...) NAME
#define UTIL_ASSERT(...) GET_MACRO(__VA_ARGS__, UTIL_ASSERT_2, UTIL_ASSERT_1)(__VA_ARGS__)


int foo() {
     UTIL_ASSERT(0,1);
}

void doo() {
     UTIL_ASSERT(0);
}
Run Code Online (Sandbox Code Playgroud)

这个比前一个好得多,因为它以某种方式验证了参数的数量。

  • 请注意,这依赖于允许您省略 `...` 参数的非标准扩展,如果您使用 `-pedantic` 进行编译,它将生成警告。(gcc/clang)。 (4认同)