我需要在 C 中编写一个可变参数宏,它必须接受零个或多个参数。
在 gcc 中,这可以通过在逗号后添加“##”来实现,例如,##____VA_ARGS____在Variadic macros with zero arguments中回答。
但是,我的构建系统中的编译器(超出我的控制范围)不理解,##语法,因此不会吞下逗号。
有我可以使用的解决方法吗?
谢谢!
使用Jens 所阐述的简化版本,下面描述了一种可能的方法。
E_用于注入参数,而I_用于引起宏的间接调用。V_需要添加额外的间接级别,这对于某些编译器来说似乎是必需的。
#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_则不展开。to 的第一个参数MAC_Y变为E_ ... () 0(其中...第一个参数是什么),第二个参数为MAC_Yis 1。这允许MAC_Y调用MAC_0或MAC_1。