C C++带多个参数的宏(...
与__VA_ARGS__
详解)
1. 环境
- gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
2.'...'与__VA_ARGS__
这里的...
代表多个参数,在宏展开时,编译器会经...
的参数替换__VA_ARGS__
例1:main.c文件敲入如下代码
#define debug(format, ...) printf (format, __VA_ARGS__)
#include <stdio.h>
void main(){
debug("Hello %s\n", "world");
}
使用预编译命令gcc -E main.c -o main.i
看看展开后是什么效果:
void main(){
printf ("Hello %s\n", "world");
}
3. 多参数别名
__VA_ARGS__
这个名字似乎很难写,gcc支持另一种更加人性化的写法:
例2:
#define debug(format, args...) printf (format, args)
#include <stdio.h>
void main(){
debug("Hello %s\n", "world");
}
展开后效果跟第一种写法是一样的:
void main(){
printf ("Hello %s\n", "world");
}
4. 空参数与##
前面两个例子都传入了两个参数,如果...
没有传进参数会发生什么事情呢:
#define debug(format, ...) printf (format, __VA_ARGS__)
#include <stdio.h>
void main(){
debug("Hello world\n");
}
展开后:
void main(){
printf ("Hello world\n", );
}
可以看到Hello world后面带来一个,
这个时候就会导致编译出错。##
的出现就是为了解决这个问题:
当...
没有传进参数时,预编译器会将最后面的,
删除
#define debug(format, ...) printf (format, ##__VA_ARGS__)
#include <stdio.h>
void main(){
debug("Hello world\n");
}
展开后效果:
void main(){
printf ("Hello world\n");
}
5. 稍微复杂的例子
项目中也会加上调用的行号,方法名称以方便debug:
#define __log(...) \
do \
{ \
printf(__VA_ARGS__); \
} while(0)
#define __format(__fmt__) "%d " __fmt__ "\n"
#define log(__fmt__, ...) \
do \
{ \
__log(__format(__fmt__), __LINE__,##__VA_ARGS__); \
}while(0)
#include <stdio.h>
void main(){
log("Hello %s", "world");
}
6. 总结
一定要看官方文档,看官方文档,看官方文档。重要的事情说三遍,尽早养成看官方文档的习惯。