我想做这样的事情:
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define MULTIARG() ARG1, ARG2, ARG3
NEED3ARGS( MULTIARG() )
我希望它能输出如下内容:
( "[" "ARG1" " + " "ARG2" " + " "ARG3" "]" )
但我有:
$ cpp multiarg.c
# 1 "multiarg.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "multiarg.c"
multiarg.c:4:23: error: macro "NEED3ARGS" requires 3 arguments, but only 1 given
NEED3ARGS
有没有办法用ANSI-C / GNU GCC和C预处理器做我想做的事?
谢谢!
答案 0 :(得分:12)
你需要一些间接。用C99:
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define INVOKE_NEED3ARGS(...) NEED3ARGS(__VA_ARGS__)
#define MULTIARG() ARG1, ARG2, ARG3
INVOKE_NEED3ARGS( MULTIARG() )
(C99不是严格要求的;您可以用固定的宏替换可变参数宏。)
如果需要使用Visual C ++编译源代码,则需要更多间接(因为a compiler bug):
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define INVOKE_NEED3ARGS_(...) NEED3ARGS __VA_ARGS__
#define INVOKE_NEED3ARGS(...) INVOKE_NEED3ARGS_((__VA_ARGS__))
#define MULTIARG() ARG1, ARG2, ARG3
INVOKE_NEED3ARGS( MULTIARG() )
至于为什么间接是需要的:宏参数在被替换到替换列表之前不会被评估和宏替换。因此,当您尝试NEED3ARGS(MULTIARG())
时,{<1}}将在 宏调用开始后才会被评估,因此将其视为单个参数。
MULTIARG()
宏确保在调用INVOKE_NEED3ARGS
之前完全评估其参数。 NEED3ARGS
替换为__VA_ARGS__
的宏替换参数,即INVOKE_NEED3ARGS
,然后使用这些参数调用ARG1, ARG2, ARG3
。
答案 1 :(得分:6)
是,
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define MULTIARG() ARG1, ARG2, ARG3
#define NEED1ARG(ARG) NEED3ARGS(ARG)
NEED1ARG( MULTIARG() )
您需要将其包装在另一个宏调用中,以便在调用NEED3ARGS
之前扩展参数。
答案 2 :(得分:1)
添加James McNellis的答案,如果你需要将这个技巧应用于许多类似函数的宏(flm),你可以定义一个“调用”宏来为你做这个技巧。这是一个完整的工作示例:
#include<cstdio>
int f(int x,int y) { return x + y; }
#define g(x,y) x+y
#define XY 1,2
#define _g(arg) g(arg)
#define invoke(flm,...) flm(__VA_ARGS__)
int main(int argc, char ** argv)
{
printf("%d\n",f(XY)); // functions are easy
printf("%d\n",_g(XY)); // Jam,es' way
printf("%d\n",invoke(g,XY)); // with generic invoke flm
return 0;
}