在GNU C中,宏可以接受可变数目的参数,就象函数一样。它允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏。可变参数宏就像下面这个样子:
#define debug(...) printf(__VA_ARGS__)
|
缺省号代表一个可以变化的参数表。使用保留名 __VA_ARGS__ 把参数传递给宏。当宏的调用展开时,实际的参数就传递给 printf()了。
Debug(
"Y = %d\n"
, y);
|
而处理器会把宏的调用替换成:
1
|
printf
(
"Y = %d\n"
, y);
|
可变参数宏不被ANSI/ISO C++ 所正式支持。因此,你应当检查你的编译器,看它是否支持这项技术。
gcc的预处理提供的可变参数宏定义真是好用:
1
2
3
4
5
6
|
#ifdef DEBUG
#define dbgprint(format,args...) \
fprintf
(stderr, format, ##args)
#else
#define dbgprint(format,args...)
#endif
|
如此定义之后,代码中就可以用dbgprint了,例如dbgprint("%s", __FILE__);
新的C99规范支持了可变参数的宏
具体使用如下:
以下内容为程序代码:
1
2
3
4
5
6
7
8
|
#include <stdarg.h>
#include <stdio.h>
#define LOGSTRINGS(fm, ...) printf(fm,__VA_ARGS__)
int
main()
{
LOGSTRINGS(
"hello, %d "
, 10);
return
0;
}
|
GCC始终支持复杂的宏,它使用一种不同的语法从而可以使你可以给可变参数一个名字,如同其它参数一样。例如下面的例子:
1
|
#define debug(format, args...) fprintf (stderr, format, args)
|
在上面的例子中,编译器仍然会有问题(complain),因为宏展开后,里面的字符串后面会有个多余的逗号。
为了解决这个问题,CPP使用一个特殊的'##'操作。书写格式为:
1
|
#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
|
果可变参数被忽略或为空,'##'操作将使预处理器(preprocessor)去除掉它前面的那个逗号
##还可以起到替换作用
如:
如:
1
|
#define FUN(IName) IName##_ptr
|
这里将会把IName变成实际数据.