4

私は次のマクロを持っています:

#define CONCATENATE(arg1, arg2)  arg1##arg2

#define FOR_EACH_1(what, x, ...) what(x)
#define FOR_EACH_2(what, x, ...) what(x) FOR_EACH_1(what, __VA_ARGS__)
#define FOR_EACH_3(what, x, ...) what(x) FOR_EACH_2(what, __VA_ARGS__)
#define FOR_EACH_4(what, x, ...) what(x) FOR_EACH_3(what, __VA_ARGS__)
#define FOR_EACH_5(what, x, ...) what(x) FOR_EACH_4(what, __VA_ARGS__)
#define FOR_EACH_6(what, x, ...) what(x) FOR_EACH_5(what, __VA_ARGS__)
#define FOR_EACH_7(what, x, ...) what(x) FOR_EACH_6(what, __VA_ARGS__)
#define FOR_EACH_8(what, x, ...) what(x) FOR_EACH_7(what, __VA_ARGS__)

#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0

#define FOR_EACH_(N, what, x, ...) CONCATENATE(FOR_EACH_, N)(what, x, __VA_ARGS__)
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, __VA_ARGS__), what, x, __VA_ARGS__)

これらは私のテストケースです:

// does not work as intended (with one argument)
#define SOME(x) int x;
FOR_EACH(SOME, y)

// fine with 2 and more
FOR_EACH(SOME, y1, y2);
FOR_EACH(SOME, y3, y4, y5, y6);

// works fine even for one argument
#define ONLY(x) x
int FOR_EACH(ONLY, x);

誰かが私に、たった1つの引数でこの事件について私が間違っていることを説明してもらえますか#define SOME(x) int x

でコンパイルするとgcc -E macro.c -o macro.lol、結果が得られます。

int y; int ;  /* <-- that's wrong, why??? */

int y1; int y2;;
int y3; int y4; int y5; int y6;;


int x ;       /* <-- works as supposed */
4

2 に答える 2

4

FOR_EACH問題は、 (whatx)に2つの引数を渡すと、__VA_ARGS__展開が何もなくなり、の呼び出しに末尾のコンマがあるFOR_EACH_NARGため、2に展開され、したがって展開されることFOR_EACH_2です。

末尾のコンマを削除します。これを行うには、の代わりにusingの非標準拡張子を使用します。これにより、が空の場合にのみ、その前のコンマが削除されます。より標準に準拠したバージョンの場合は、とを1つのパラメーターに組み合わせることができます。##__VA_ARGS____VA_ARGS____VA_ARGS__x__VA_ARGS__

#define FOR_EACH_(N, what, ...) CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__)
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
于 2012-11-06T15:43:18.220 に答える
1

コンパイラから、私たちに知らせなかったという警告が表示されているはずです。

私の推測では、ここにあなたのマクロがあります

#define FOR_EACH_1(what, x, ...) what(x)

パーツが見えないので間違ってい__VA_ARGS__ます。私はそれを癒す2つの方法を見ます

#define FOR_EACH_1(what, ...) what(__VA_ARGS__)

#define FOR_EACH_1(what, x) what(x)

このようなマクロであなたを傷つける可能性のあるもう1つのことは、Cで慣れているものとは異なる引数番号のカウントです。

#define MUCH(...)
#define NONE()

NONE   //<- this is considered receiving no argument
MUCH   //<- this receives one argument, the empty token list

プリプロセッサを学習するためにこれを行っている場合、これは問題ありません:)この種の問題の一般的な解決策が本当にあれば、Boost(ただしこれは主にC ++です)とP99を調べることができます。

于 2012-11-06T15:39:15.610 に答える