Est-il possible à une macro d’évaluer plusieurs arguments à un autre?

J’aimerais faire quelque chose comme ça:

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

Et je m’attendais à ce qu’il produise quelque chose comme:

 ( "[" "ARG1" " + " "ARG2" " + " "ARG3" "]" ) 

Mais à la place j’ai:

 $ cpp multiarg.c # 1 "multiarg.c" # 1 "" # 1 "" # 1 "multiarg.c" multiarg.c:4:23: error: macro "NEED3ARGS" requires 3 arguments, but only 1 given NEED3ARGS 

Existe-t-il un moyen de faire ce que je veux en utilisant ANSI-C / GNU GCC et le préprocesseur C?

Merci!

Vous avez besoin d’un peu d’indirection. Avec C99:

 #define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" ) #define INVOKE_NEED3ARGS(...) NEED3ARGS(__VA_ARGS__) #define MULTIARG() ARG1, ARG2, ARG3 INVOKE_NEED3ARGS( MULTIARG() ) 

(C99 n’est pas ssortingctement requirejs; vous pouvez remplacer la macro variadique par une macro à arité fixe.)

Si vous devez comstackr votre source à l’aide de Visual C ++, vous aurez besoin de davantage d’indirection (à cause d’ un bogue du compilateur ):

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

En ce qui concerne la raison pour laquelle l’ indirection est nécessaire: un argument de macro n’est pas évalué et remplacé par une macro tant qu’il n’est pas substitué dans la liste de remplacement. Ainsi, lorsque vous essayez NEED3ARGS(MULTIARG()) , MULTIARG() ne sera évalué qu’après le début de l’ invocation de la macro. Il est donc traité comme un argument unique.

La macro INVOKE_NEED3ARGS garantit que ses arguments sont complètement évalués avant que NEED3ARGS soit NEED3ARGS . __VA_ARGS__ est remplacé par les arguments de macro remplacés par INVOKE_NEED3ARGS , qui est ARG1, ARG2, ARG3 , puis NEED3ARGS est NEED3ARGS avec ces arguments.

Oui,

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

Vous devez l’envelopper dans un autre appel de macro afin que l’argument soit développé avant que NEED3ARGS soit appelé.

En ajoutant à la réponse de James McNellis, si vous devez appliquer cette astuce à de nombreuses macros de type fonction (flm), vous pouvez définir une seule macro “invocation” pour faire l’affaire à votre place. Voici un exemple de travail complet:

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