prev up next   top/contents search

comp.lang.c FAQ 列表· 问题 10.26

Q我如何编写一个接受可变数量参数的宏,或者使用预处理器来“关闭”一个接受可变数量参数的函数调用?


A一个流行的技巧是使用一个包含在圆括号中的“参数”来定义和调用宏,该参数在宏展开时成为函数(如printf:

	#define DEBUG(args) (printf("DEBUG: "), printf args)

	if(n != 0) DEBUG(("n is %d\n", n));
)的整个参数列表,包括圆括号。明显的缺点是调用者必须始终记住使用额外的圆括号。另一个问题是宏展开不能插入任何额外的参数(即,DEBUG()不能展开为类似fprintf(debugfd, ...)).

gcc有一个扩展允许函数式宏接受可变数量的参数,但这并非标准。其他可能的解决方案包括

(这些都需要用户小心,并且都相当难看。)

C99 为具有可变长度参数列表的函数式宏引入了正式支持。该符号...可以出现在宏“原型”的末尾(就像它在 varargs 函数中一样),并且伪宏__VA_ARGS__在宏定义中,在调用时会被可变参数替换。

最后,您始终可以使用一个真正的函数,它可以以一种定义明确的方式接受可变数量的参数。请参阅问题 15.415.5。(如果您需要宏替代,可以尝试使用函数加上一个非函数式宏,例如#define printf myprintf .)

当您想关闭调试打印输出时,您可以使用您的调试宏的另一个版本

	#define DEBUG(args) /* empty */
或者,如果您使用的是真实函数调用,可以使用更多的预处理器技巧来删除函数名但不删除参数,例如
	#define DEBUG (void)
or
#define DEBUG if(1) {} else printf or
#define DEBUG 1 ? 0 : (void)
(这些技巧基于一个假设,即好的优化器会移除任何“死”printf调用或退化的强制转换为 void 的圆括号逗号表达式。)另请参阅问题 10.14

其他链接: 更多想法

参考文献: C9X Sec. 6.8.3, Sec. 6.8.3.1


prev up next   contents search
关于此 FAQ 列表   关于 Eskimo   搜索   反馈   版权

Eskimo North 托管