Q我如何编写一个接受可变数量参数的宏,或者使用预处理器来“关闭”一个接受可变数量参数的函数调用?
A一个流行的技巧是使用一个包含在圆括号中的“参数”来定义和调用宏,该参数在宏展开时成为函数(如printf:
#define DEBUG(args) (printf("DEBUG: "), printf args) if(n != 0) DEBUG(("n is %d\n", n));)的整个参数列表,包括圆括号。明显的缺点是调用者必须始终记住使用额外的圆括号。另一个问题是宏展开不能插入任何额外的参数(即,DEBUG()不能展开为类似fprintf(debugfd, ...)).
gcc有一个扩展允许函数式宏接受可变数量的参数,但这并非标准。其他可能的解决方案包括
#define DEBUG(args) (printf("DEBUG: "), printf(args)) #define _ , DEBUG("i = %d" _ i);
#define DEBUG fprintf(stderr, DEBUG "%d", x);
C99 为具有可变长度参数列表的函数式宏引入了正式支持。该符号...可以出现在宏“原型”的末尾(就像它在 varargs 函数中一样),并且伪宏__VA_ARGS__在宏定义中,在调用时会被可变参数替换。
最后,您始终可以使用一个真正的函数,它可以以一种定义明确的方式接受可变数量的参数。请参阅问题 15.4 和 15.5。(如果您需要宏替代,可以尝试使用函数加上一个非函数式宏,例如#define printf myprintf .)
当您想关闭调试打印输出时,您可以使用您的调试宏的另一个版本
#define DEBUG(args) /* empty */或者,如果您使用的是真实函数调用,可以使用更多的预处理器技巧来删除函数名但不删除参数,例如
#define DEBUG (void) or(这些技巧基于一个假设,即好的优化器会移除任何“死”printf调用或退化的强制转换为 void 的圆括号逗号表达式。)另请参阅问题 10.14。
#define DEBUG if(1) {} else printf or
#define DEBUG 1 ? 0 : (void)
其他链接: 更多想法
参考文献: C9X Sec. 6.8.3, Sec. 6.8.3.1