当我使用宏参数计数器时,如果删除一个间接级别,我发现它无效。
原始代码:
#define COUNT_ARGS(...) \
COUNT_INDIR(__VA_ARGS__,COUNT_DOWN())
#define COUNT_INDIR(...) \
COUNT_HELPER(__VA_ARGS__)
#define COUNT_HELPER( \
_1, _2, _3, _4, _5, N,...) N
#define COUNT_DOWN() \
5, 4, 3, 2, 1, 0
COUNT_ARGS(1,2,3);
我的编辑版本:
#define COUNT_ARGS(...) \
COUNT_HELPER(__VA_ARGS__,COUNT_DOWN())
#define COUNT_HELPER( \
_1, _2, _3, _4, _5, N,...) N
#define COUNT_DOWN() \
5, 4, 3, 2, 1, 0
COUNT_ARGS(1,2,3);
我收到以下消息
错误:宏“COUNT_HELPER”需要7个参数,但只有4个
我的猜测是COUNT_DOWN()传递给COUNT_HELPER而不进行扩展。但我从Argument Prescan读到,宏参数在被替换为宏体之前已经完全展开。矛盾的行为让我感到困惑。
答案 0 :(得分:2)
类功能宏的扩展在不连续的阶段运行:
参数从参数列表中标识出来。宏的参数列表中每个命名参数必须有一个参数,如果宏是可变参数,则至少还有一个参数。
每个参数都是完全宏扩展的。
宏调用替换为宏的替换文本,扩展的参数替换为相应的参数名称。
重新扫描扩展以进行其他宏扩展。
(忽略了#
和##
运算符的影响,这些运算符在这里没有发挥作用。)
我怀疑你的困惑是因为没有意识到步骤(2)与步骤(1)完全分离。一旦识别出宏参数,就会设置它们的编号以及它们与宏参数的对应关系。无论扩展文本的性质如何,扩展它们都不会对其进行修改。或者,也许您不理解宏的替换文本中的宏调用不会在宏定义本身中扩展,而是在扩展宏的过程的第(4)步中。
因此,鉴于这些(原始)定义......
#define COUNT_ARGS(...) \
COUNT_INDIR(__VA_ARGS__,COUNT_DOWN())
#define COUNT_INDIR(...) \
COUNT_HELPER(__VA_ARGS__)
#define COUNT_HELPER( \
_1, _2, _3, _4, _5, N,...) N
#define COUNT_DOWN() \
5, 4, 3, 2, 1, 0
......这是扩展的序列:
COUNT_ARGS(1,2,3);
COUNT_INDIR(1,2,3,COUNT_DOWN());
COUNT_HELPER(1,2,3,5,4,3,2,1,0);
3;
另一方面,鉴于您修改后的定义......
#define COUNT_ARGS(...) \
COUNT_HELPER(__VA_ARGS__,COUNT_DOWN())
#define COUNT_HELPER( \
_1, _2, _3, _4, _5, N,...) N
#define COUNT_DOWN() \
5, 4, 3, 2, 1, 0
......扩展是这样的:
COUNT_ARGS(1,2,3);
COUNT_HELPER(1,2,3,COUNT_DOWN());
错误强>
正如错误消息告诉您的那样,COUNT_HELPER()
提供的参数太少。那个COUNT_HELPER()
的扩展会产生一个以逗号分隔的列表,这一点无关紧要。
导致COUNT_DOWN()
扩展为COUNT_HELPER()
的多个参数是原始COUNT_INDIR()
宏的全部目的。