可变参数宏 , Variadic Macros

说起可变参数,立即想到的就是printf(),scanf()了。可变参数就是有一个固定的格式控制参数,后面再根据格式控制参数接若干参数。

         这里先讨论可变参数宏。

         我们一般在Debug需要打印调试信息的时候,需要可变参数的宏。

         一, vc(C99)的复杂宏。

         参考msdn(http://msdn2.microsoft.com/en-us/library/ms177415.aspx )。使用这种复杂宏时,省略号是格式控制参数,而标识符__VA_ARGS__用来插入另外的参数。__VA_ARGS__ 将"..." 传递给宏。

例如:

#include <stdio.h>

#define CHECK1(x, ...) if (!(x)) { printf(__VA_ARGS__); }
#define CHECK2(x, ...) if ((x)) { printf(__VA_ARGS__); }
#define CHECK3(...) { printf(__VA_ARGS__); }

int main( )
{
        CHECK1(0, "here %s %s %s", "are", "some", "varargs1(1)/n");
        CHECK1(1, "here %s %s %s", "are", "some", "varargs1(2)/n");     // won't print
        CHECK2(0, "here %s %s %s", "are", "some", "varargs2(3)/n");     // won't print
        CHECK2(1, "here %s %s %s", "are", "some", "varargs2(4)/n");
        CHECK3("here %s %s %s", "are", "some", "varargs3(5)/n");
        return 0;
}

输出为:

here are some varargs1(1)
here are some varargs2(4)
here are some varargs3(5)

         二,GCC中的复杂宏

         GCC支持C99中的复杂宏,但G++不支持。GCC使用一种不同的语法,给可变参数一个名字,如同其它参数一样。

#define CHECK1(x,format, args...) if(x) { printf (format, args); }

         显然这样易于描述而且可读性更强。


          三,CHECK("Some messges.")的情况

         这时由于宏展开后有个多余的逗号,,将导致编译错误.。为了解决这个问题,CPP使用一个特殊的“##”操作。

        #define CHECK(format, ...) printf ( format, ## __VA_ARGS__)

        这里,如果可变参数被忽略或为空,“##”操作将使预处理器去除掉它前面的那个逗号。如果在宏调用时,确实提供了一些可变参数,GNU CPP也会工作正常,它会把这些可变参数放到逗号的后面。

         四,类似printf()的技巧

         用一个被括弧括起来的 “参数”来定义和调用宏,参数在宏扩展的时候成为类似printf()函数中的格式控制字符串那样的参数列表。

         #define CHECK(args) (printf("DEBUG: "), printf(args))

         用了括号。

/

   今天来说说宏。什么?宏也能可变参数?是的,你没有听错,带参数的宏和函数一样,同样支持可变参数。下面通过一个小程序加以说明。

#include

#include

#define OUTSCREEN(msg, ...) printf(msg,__VA_ARGS__)

int main(int argc, char* argv[])

{

      OUTSCREEN("Hello World!n%s", "__This is a MACRO!n");

      return 0;

}

      这个可变参数的宏是新的 C99 规范中新增的,目前似乎只有 gcc 支持( VC6.0 的编译器不支持)。

#define OUTSCREEN(msg, ...) printf(msg, __VA_ARGS__)

int main(int argc, char* argv[])

{

      OUTSCREEN("Hello World!n%s", "__This is a MACRO!n");

      return 0;

}

     假如我们将上面的代码稍作一下修改,变成下面的样子。

#define OUTSCREEN(msg, ...) printf(msg, __VA_ARGS__)

int main(int argc, char* argv[])

{

      OUTSCREEN("Hello World!");

      return 0;

}

     注意我仅仅是将 main 函数里的 OUTSCREEN 做了修改,这时可变参数的个数为 0 了。但是编译的时候 gcc 却报错:

In function `main':

error: parse error before ')' token

     什么原因导致出错呢?把宏展开一下看看,原来是 "," 惹得祸。那么这种参数个数可以为 0 的宏要怎么写呢? C99 的规范没有定义这个, gcc 对此做了扩展。重新定义 OUTSCREEN 宏如下:

#define OUTSCREEN(msg, ...) printf(msg, ##__VA_ARGS__)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值