【问题标题】:Swallowing comma in variadic macros on compilers that do not recognise ##在无法识别的编译器上吞下可变参数宏中的逗号 ##
【发布时间】:2011-12-09 11:18:53
【问题描述】:

我需要用 C 语言编写一个可变参数宏,它必须接受零个或多个参数。

在 gcc 中,可以通过在逗号后添加“##”来实现,例如,##____VA_ARGS____ 已在 Variadic macros with zero arguments 中回答。

但是,我的构建系统中的编译器(超出我的控制范围)不理解 ,## 语法,因此不会吞下逗号。

有没有我可以使用的解决方法?

谢谢!

【问题讨论】:

  • 在 , 和 ## 之间插入一个空格?
  • DipSwitch:谢谢,但我遇到了同样的问题。

标签: c gcc macros comma variadic


【解决方案1】:

是的,gcc 吞下逗号是非标准的,你不应该依赖它。

使用符合 C99 的预处理器,您可以通过测试作为空标记的宏参数来实现类似的效果。有关其工作原理的想法,您可以查看 here,对于简化此类功能的编程的一整套预处理器宏,请参阅 P99

【讨论】:

  • 谢谢,虽然这似乎是一种解决方法。有没有其他方法可以做到这一点?
  • 请使用链接中的实际解决方法扩展此答案...或至少如何使用 P99
  • @AnttiHaapala:我提供了 Jens 博文的简化版本。
【解决方案2】:

使用Jens spelled out 的简化版本,一种可能的方法如下所述。

E_ 用于注入参数,而I_ 用于导致间接调用宏。 V_ 需要添加额外的间接级别,some compilers 似乎需要这样做。

#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define E_() _,

现在,假设您需要一个宏 MAC 来处理 0、1 或 2 个参数:

MAC(1, 2);
MAC(1);
MAC();

一种可能的实现可能如下所示:

#define MAC_X(_2,_1,X,...) MAC_##X
#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))

#define MAC_2(...) function_for_2(__VA_ARGS__)
#define MAC_1(...) function_for_1(__VA_ARGS__)
#define MAC_0(...) function_for_0(__VA_ARGS__)

#define MAC_Y(_1,Y,...) MAC_##Y
#define MAC__(...) I_(MAC_Y, E_ __VA_ARGS__ () 0, 1)(__VA_ARGS__)

将其扩展为 3 个参数相对简单。唯一的麻烦是检测 1 或 0 个参数,它们不会改变:

-#define MAC_X(_2,_1,X,...) MAC_##X
-#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))
+#define MAC_X(_3,_2,_1,X,...) MAC_##X
+#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,3,2,_))(__VA_ARGS__))

+#define MAC_3(...) function_for_3(__VA_ARGS__)
 #define MAC_2(...) function_for_2(__VA_ARGS__)

对于超过 1 个参数,MAC 宏扩展为 MAC_2(或 MAC_3)。但是,对于 1 或 0 个参数,MAC 宏扩展为 MAC__

MAC__ 宏应用 Jens 的技巧来检测是否传递了 1 个或 0 个参数。它使用E_ 辅助宏来做到这一点,并在E_() 之间注入它的参数,这将导致它被调用。如果有 0 个参数,则调用 E_,并注入一个参数。注入的参数导致0 成为MAC_Y 选择的第二个参数。如果有 1 个参数,E_ 不会展开。 MAC_Y 的第一个参数变为E_ ... () 0(其中... 是第一个参数),MAC_Y 的第二个参数是1。这允许MAC_Y 调用MAC_0MAC_1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    • 2015-05-14
    • 2011-04-03
    • 2014-09-04
    • 2016-02-06
    • 1970-01-01
    相关资源
    最近更新 更多