先看下以下2个宏定义:
#define LOG(fmt, ...) printf(fmt, __VA_ARGS__) /* C99标准 */
#define LOG(fmt, args...) printf(fmt, args) /* gcc中支持 */
这或许能够满足一部分需求了,但是并不完美,因为这2个宏定义的可变参数部分不能省略,否则编译报错。所以这里就有必要加上“##”连接符,它的作用是对token(本例fmt和args都是token)的连接,如果token为空,则可以忽略掉而不进行连接,相比之下以下2个宏定义的可用性更高:
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) /* C99标准 */
#define LOG(fmt, args...) printf(fmt, ##args) /* gcc中支持 */
示例:
#include <stdio.h>
#define LOG1(fmt, ...) printf(fmt, __VA_ARGS__)
#define LOG2(fmt, ...) printf(fmt, ##__VA_ARGS__)
int main(int argc, char **argv)
{
// LOG1("hello, log1!\n"); // 编译会报错,因为没有提供可变参数
LOG1("hello, %s!\n", "log1");
LOG2("hello, log2!\n"); // 编译正常,因为使用了连接符“##”
LOG2("hello, %s!\n", "log2");
return 0;
}
既然使用到宏定义来Debug,那么常常搭配#ifdef、#else、#end宏定义来控制输出:
#ifdef ENABLE_LOG
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif