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 预处理器来做我想做的事?

谢谢!

4

3 回答 3

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++ 编译源代码,则需要更多的间接性(因为编译器错误):

#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()),直到宏调用开始MULTIARG()才会被评估,因此它被视为单个参数。

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

于 2012-04-19T18:14:36.590 回答
6

是的,

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

NEED1ARG( MULTIARG() )

您需要将其包装在另一个宏调用中,以便在调用之前扩展参数NEED3ARGS

于 2012-04-19T18:15:07.487 回答
1

Adding to James McNellis's answer, if you need to apply this trick to many function-like macros (flm), you could define a single "invoke" macro to do the trick for you. Here's a complete working example:

#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;
}
于 2014-03-21T20:00:04.817 回答