2012-04-19 101 views
6

我想要做这样的事情:是否有可能向另一个宏评估多个参数?

#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预处理器来完成我想要的工作?

谢谢!

回答

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()) 

至于为什么需要间接:宏参数不是evalu直到它被替换到替换列表中为止。因此,当您尝试NEED3ARGS(MULTIARG()),MULTIARG()将不会被评估,直到宏调用开始后,因此它被视为单个参数。

INVOKE_NEED3ARGS确保在调用NEED3ARGS之前完全评估其参数。将__VA_ARGS__替换为INVOKE_NEED3ARGS的宏替换参数,即ARG1, ARG2, ARG3,然后用这些参数调用NEED3ARGS

6

是,

#define NEED3ARGS(a1,a2,a3) ("[" #a1 " + " #a2 " + " #a3 "]") 
#define MULTIARG() ARG1, ARG2, ARG3 
#define NEED1ARG(ARG) NEED3ARGS(ARG) 

NEED1ARG(MULTIARG()) 

你需要用它在另一个宏调用,这样NEED3ARGS调用之前的说法得到扩大。

1

添加到James McNellis的回答中,如果您需要将此技巧应用于许多类似功能的宏(flm),您可以定义一个“invoke”宏来为您完成技巧。这是一个完整的工作示例:

#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; 
}