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

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;
}
于 2014-03-21T20:00:04.817 に答える