C语⾔中宏定义之##⽤于可变参数
GCC ⽀持复杂的宏,它使⽤⼀种不同的语法,使你可以给可变参数⼀个名字,如同其它参数⼀样,⽐如:
引⽤
#define debug(format, ) fprintf(stderr, format, args)
这种定义可读性更强,也更容易描述。完整测试代码:
引⽤
#include <stdio.h>
#define debug(format, ) fprintf(stderr, format, args)
int main()
{
char a[20] = "hello world\n";
int i = 10;
debug("i = %d, %s", i, a);
fprintf作用return 0;
}
运⾏输出:
引⽤
beyes@linux-beyes:~/C/micro> ./
i = 10, hello world
但是上⾯的定义仍存在⼀点问题,如果把上⾯的代码改为下⾯的:
引⽤
#include <stdio.h>
#define debug(format, ) fprintf(stderr, format, args)
int main()
{
debug("hello world\n");
return 0;
}
那么在编译时会提⽰以下错误:
引⽤
beyes@linux-beyes:~/C/micro> gcc -g mic.c -
mic.c: In function ‘main’:
mic.c:10: error: expected expression before ‘)’ token
提⽰缺少右边括号。这是因为,当宏展开后,"hello world\n" 代⼊ format,然⽽,在其后还紧跟着⼀个逗号,但是这个逗号后⾯是期望有args 参数的,但这⾥却没有,所以宏不能展开完全,故⽽⽆法编译通过。那么,再改⼀下宏定义:
引⽤
#include <stdio.h>
#define debug(format, ) fprintf(stderr, format, ##args)
int main()
{
debug("hello world\n");
return 0;
}
这时候,再编译运⾏及输出:
引⽤
beyes@linux-beyes:~/C/micro> gcc -g mic.c -
beyes@linux-beyes:~/C/micro> ./
hello world
编译通过,并正常输出。上⾯的代码,在 fprintf() 中的 args 前⾯加了两个 # 号 ##。
## 号的作⽤是:
如果可变参数部分( ) 被忽略或为空,那么 "##" 操作会使预处理器 (preprocessor) 去掉它前⾯的那个逗号。如果在调⽤宏时,确实提供了⼀些可变参数,GNU C 也会正常⼯作,它会把这些可变参数放在逗号的后⾯;如果没有提供,它就会⾃动去掉前⾯的逗号,使宏结束展开 ---- 补充完右边括号。
另外,假如按照 C99 的定义来⽤,改宏为:
引⽤
#define debug(format, ) fprintf(stderr, format, ##__VA_ARGS__)
那么编译会出错:
引⽤
beyes@linux-beyes:~/C/micro> gcc -g mic.c -
mic.c:3:58: warning: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro
mic.c:9:1: error: pasting "," and "__VA_ARGS__" does not give a valid preprocessing token
mic.c: In function ‘main’:
mic.c:9: error: ‘__VA_ARGS__’ undeclared (first use in this function)
mic.c:9: error: (Each undeclared identifier is reported only once
mic.c:9: error: for each function it appears in.)
原因在于, 和 ##__VA_ARGS__ 是不匹配的,正确的匹配应该是:
引⽤
#define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
注意,... 省略号对应的就是 __VA_ARGS__
⼀般的,定义可变参数宏的⼀个流⾏⽅法,形如:
引⽤
#define DEBUG(args) (printf("DEBUG: "), printf args)
if(n != 0) DEBUG(("n is %d\n", n));
这个⽅法的⼀个缺点是,要记住⼀对额外的括弧。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论