下面的示例在VisualStudio 2010及以上版本、启用了非标准扩展的gcc和clang中都可以正常工作。在Microsoft编译器中,它假定AUGMENTER宏中的尾逗号将在参数计数为零时被预处理器移除。这是非标准的,也已经在其他地方报告过。在gcc和clang中,它使用广泛知晓的## __VA_ARGS__
非标准扩展。
#include <stdio.h>
#ifdef _MSC_VER
#define EXPAND(x) x
#define __NARGS(_1, _2, _3, _4, _5, VAL, ...) VAL
#define NARGS_1(...) EXPAND(__NARGS(__VA_ARGS__, 4, 3, 2, 1, 0))
#define AUGMENTER(...) unused, __VA_ARGS__
#define NARGS(...) NARGS_1(AUGMENTER(__VA_ARGS__))
#else
#define NARGS(...) __NARGS(0, ## __VA_ARGS__, 5,4,3,2,1,0)
#define __NARGS(_0,_1,_2,_3,_4,_5,N,...) N
#endif
int main()
{
printf("%d\n", NARGS());
printf("%d\n", NARGS(1));
printf("%d\n", NARGS(1, 2));
fflush(stdout);
#ifdef _MSC_VER
printf("\n");
printf("%d\n", NARGS_1(1));
printf("%d\n", NARGS_1(1, 2));
printf("%d\n", NARGS_1(1, 2, 3));
#endif
return 0;
}
宏已经在真实的编译器中进行了测试,其中包括 Wandbox 和 Webcompiler