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);

请有人向我解释我在这个案子中做错了什么,只有一个论点,#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(只是whatand x)时,__VA_ARGS__扩展为空,并且您在对 的调用中有一个尾随逗号FOR_EACH_NARG,因此它扩展为 2 并因此扩展FOR_EACH_2

你想摆脱那个尾随的逗号。您可以通过使用 using 的非标准扩展##__VA_ARGS__不是来做到这一点__VA_ARGS__,它仅在逗号__VA_ARGS__为空时删除它之前的逗号。对于更符合标准的版本,您可以将xand组合__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__一部分。我看到了两种治疗方法

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

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

使用此类宏可能会伤害您的另一件事是参数编号的计数与您习惯使用 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 回答