【问题标题】:Detect presence or absence of arguments in a C macro检测 C 宏中是否存在参数
【发布时间】:2014-02-23 19:01:59
【问题描述】:

如何定义一个 C 宏 IFARGS(YES, NO, ...),使得在没有附加参数的情况下调用 IFARGS 会生成 NO,而使用一个或多个参数调用 IFARGS 会生成 YES

我有一个使用 GCC 的答案(见下文),但如果可能的话,我更喜欢 C99 的答案(或证明它不可能)。

【问题讨论】:

    标签: c c-preprocessor variadic-macros


    【解决方案1】:
    #define GET(_0, _1) _0  // Return the first of two arguments
    #define GET_(_0, _1) _1  // Return the second of two arguments
    
    #define JOIN(_0, _1) _0 ## _1  // Concatenate two arguments
    #define EJOIN(_0, _1) JOIN(_0, _1)  // Expand macros and concatenate
    
    #define FIRST(_, ...) _  // Truncate everything after first comma
    #define EFIRST(_) FIRST(_)  // Expand argument and pass to FIRST
    
    #define REST(_0, ...) __VA_ARGS__  // Remove everything before first comma
    
    #define GET_GET(...) \
        EJOIN(GET, EFIRST(REST(,,##__VA_ARGS__ _)))  // Branch between GET and GET_
    
    #define IFARGS(YES, NO, ...) GET_GET(__VA_ARGS__)(YES, NO)
    

    请注意,如果这在 C99 中是可能的,那么就可以模拟 ##__VA_ARGS__,如下所示:

    #define PREPEND_COMMA(...) , __VA_ARGS__
    #define NO_COMMA()
    #define PREPEND_COMMA_IF_NONEMPTY(...) IFARGS(PREPEND_COMMA, NO_COMMA, __VA_ARGS__)(__VA_ARGS__)
    

    那么, ##__VA_ARGS__ 的任何实例都可以替换为PREPEND_COMMA_IF_NONEMPTY(__VA_ARGS__)

    【讨论】:

    • 这并不是真正的答案,而只是对您自己问题的补充。
    • @JensGustedt 第一个代码框是部分解决方案 -- 它具有所需的行为,但需要 ##__VA_ARGS__,这是对 C99 宏语法的 GCC 扩展。
    • 我注意到了。对 SO 进行一些研究可能会为您提供答案。请参阅上面的链接。
    • @JensGustedt 如果您能想到不需要 GCC 的 IFARGS 的实现,请在此处发布!那真的很酷,因为正如我在上面所证明的,任何可以用##__VA_ARGS__ 实现的 宏都可以用IFARGS 实现。
    • 我做到了,你没看到我的回答吗?如果您希望扩展对 P99_IF_EMPTY 的引用,您必须自己完成。我觉得你的界面 IFARGS 不够有趣,我无法自己做。
    【解决方案2】:

    在 C99 中,可以检测一个宏参数是否为空,但是要使该宏参数具有鲁棒性以应对该参数中可能出现的所有可能性(参数本身正在扩展,包含 () 和类似的东西)是困难的。我的宏包P99 实现了这样的东西,所以你不必太担心。这样你的宏就可以实现为

    #define IFARGS(YES, NO, ...) P99_IF_EMPTY(__VA_ARGS__)(YES(__VA__ARGS__))(NO())
    

    顾名思义,P99 仅基于 C99 功能构建。

    【讨论】:

    • 如何检测 C99 中的空参数?
    • @augurar,这个是我最喜欢的搜索引擎的热门搜索:) gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments
    • 有趣;但是,该帖子中的 ISEMPTY 宏在恰好给出 16 个参数时似乎失败了。
    • 对于实际应用,这是一个很好的解决方案。我仍然对 ##__VA_ARGS__ 是否真的为宏语言添加任何“力量”,或者它是否只是一个便利功能的理论问题感兴趣。
    • @augurar,那你为什么不问那个问题?
    猜你喜欢
    • 2019-10-02
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 2018-09-05
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多