You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现__VA_OPT__反向效果?C预处理器可选参数默认值方案

实现__VA_ARGS__为空时展开默认内容的方案

要实现你需要的效果——调用MY_MACRO()时展开为default,调用MY_MACRO(arg)时展开为arg,可以借助C20标准的__VA_OPT__特性来完成,这是目前最可靠的方案。

C20 实现方案

利用__VA_OPT__在可变参数非空时生成特定标记,通过宏的条件展开实现逻辑:

#define MY_MACRO(...) \
    __VA_OPT__(__VA_ARGS__) \
    _DEFAULT_##__VA_OPT__(NON_EMPTY)

// 当传入参数时,此宏展开为空
#define _DEFAULT_NON_EMPTY
// 当无参数时,此宏展开为默认值
#define _DEFAULT default

工作原理

  • 调用MY_MACRO()时,__VA_ARGS__为空,__VA_OPT__(NON_EMPTY)展开为空,因此_DEFAULT_##__VA_OPT__(NON_EMPTY)会被替换为_DEFAULT,最终结果为default。
  • 调用MY_MACRO(arg)时,__VA_ARGS__非空,__VA_OPT__(NON_EMPTY)展开为NON_EMPTY,_DEFAULT_NON_EMPTY为空,最终结果为arg。

通用版__VA_NOT_OPT__模拟

如果你想封装一个通用的__VA_NOT_OPT__宏(仅当__VA_ARGS__为空时展开指定内容),可以这样实现:

#define _SELECT(_, EMPTY_RES, NON_EMPTY_RES, ...) EMPTY_RES
#define __VA_NOT_OPT__(content) \
    _SELECT(__VA_OPT__(,), content, /* 非空时无输出 */)

使用时直接按你示例中的方式写:

#define MY_MACRO(...) __VA_NOT_OPT__(default) __VA_ARGS__

传统预处理器方案(无C20支持)

如果编译器不支持C20,传统预处理器技巧无法完美区分“无参数”和“传递空参数”,但可以在特定场景下使用:

#define _GET_FIRST(_1, _2) _1
#define MY_MACRO(...) _GET_FIRST(__VA_ARGS__, default)

注意:这种方法有缺陷——调用MY_MACRO()时,__VA_ARGS__为空,_GET_FIRST会返回空参数而非default,仅在你能确保调用时始终传递参数,或者接受用MY_MACRO(())触发默认值时才适用。

内容的提问来源于stack exchange,提问作者Martin Fehrs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:29:51