2012-04-19 114 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; 
} 
相關問題