函数式宏中可变参数中的 ## 运算符

可变参数可能会出现在两个地方:

1,函数中

2,函数式宏中

##运算符的另外一种用法就是出现在函数式宏中。以下是书上原话:


宏定义中可变参数的部分用__VA_ARGS__表示。在宏展开时,和…对应的几个实参可以看成一个实参来替换掉__VA_ARGS__。

GCC有一种扩展用法,如果##运算符用在__VA_ARGS__前面,除了起连接Token的作用之外还有一种特殊的用法,例如内核代码net/netfilter/nf_conntrack_proto_sctp.c中的:

#define DEBUGP(format,…) printk(format, ## __VA_ARGS__)

内核函数printk类似于printf,也带有格式化字符串和可变参数,由于内核不能调用libc的库函数,所以另外实现了这样一个打印函数。这函数式宏定义的可以这样调用:DEBUG(“info no. %d”, 1), 也可以这样调用:DEBUG(“info”)。后者相当于可变参数部分传了一个空参数,但展开之后并不是printk(“info”,),而是printk(“info”),当__VA_ARGS__是空码数时,##运行算符把它前面的逗号“吃”掉了。

 

例:

#include<stdio.h>

 

#defineDEBUG(format, ...) do{\

    /*我自己的理解*/\

    /*注意此时若可变参数部分为空,即__VA_ARGS__为空,则下面心编译后为printf(format);*/\

    /*即##会吃掉它前面的逗号,否则##不会做任何事*/\

    printf(format,## __VA_ARGS__); \

}while(0)

 

intmain(){

    DEBUG("2011-8-19 20:22\n");

    return 0;

}

 

这个仅供娱乐:

#include<stdio.h>

 

#defineSTR(s) VAL(s)

#defineVAL(s) # s

 

#defineDEBUG(format, ...) do{\

    /*我自己的理解*/\

    /*注意此时若可变参数部分为空,即__VA_ARGS__为空,则下面心编译后为printf(format);*/\

    /*即##会吃掉它前面的逗号,否则##不会做任何事*/\

    printf(format,## __VA_ARGS__); \

}while(0)

 

/*此函数式宏不调用时至少传一个参数,因为运算符# 后面一定要有参数*/

#defineLKVARGS(...) printf("%s\n",VAL(__VA_ARGS__));

intmain(void){

    char *ptr_s = "world";

    char *ptr_name = "xiaoqian";

    DEBUG("2011-8-19 20:22\n");

    DEBUG("hello %s, I am %s\n", ptr_s, ptr_name);

    LKVARGS("arg1", "arg2","arg3");

    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值