用可变参数宏(variadic macros)传递可变参数表
你可能很熟悉在函数中使用可变参数表,如:

void printf(const char* format, …);

直到最近,可变参数表还是只能应用在真正的函数中,不能使用在宏中。

C99编译器标准终于改变了这种局面,它允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏。可变参数宏就像下面这个样子:

#define debug(…) printf(__VA_ARGS__) //最好定义为#define debug(…) printf(##__VA_ARGS__),后面有关于##的说明

缺省号代表一个可以变化的参数表。使用保留名 __VA_ARGS__ 把参数传递给宏。当宏的调用展开时,实际的参数就传递给 printf()了。例如:

Debug(“Y = %d\n”, y);

而处理器会把宏的调用替换成:

printf(“Y = %d\n”, y);

因为debug()是一个可变参数宏,你能在每一次调用中传递不同数目的参数:

debug(“test”); //一个参数

可变参数宏不被ANSI/ISO C++ 所正式支持。因此,你应当检查你的编译器,看它是否支持这项技术。

用GCC和C99的可变参数宏, 更方便地打印调试信息

gcc的预处理提供的可变参数宏定义真是好用:

#ifdef DEBUG
#define dbgprint(format,args...) \
fprintf(stderr, format, ##args)
#else
#define dbgprint(format,args...)
#endif

如此定义之后,代码中就可以用dbgprint了,例如dbgprint("aaa %s", __FILE__);。感觉这个功能比较Cool  :em11:

下面是C99的方法:

#define dgbmsg(fmt,...) \
             printf(fmt,##__VA_ARGS__

新的C99规范支持了可变参数的宏

具体使用如下:

以下内容为程序代码:

#include <stdarg.h> #include <stdio.h>

#define LOGSTRINGS(fm, ...) printf(fm,##__VA_ARGS__)

int main() {      LOGSTRINGS("hello, %d ", 10);      return 0; }

但现在似乎只有gcc才支持。

GNU C和C99标准中的可变参数宏(variadic macros)的更多相关文章

  1. [转载]用可变参数宏(variadic macros)传递可变参数表

    注意:_VA_ARGS__ 从VS2005才开始支持 在 GNU C 中,宏可以接受可变数目的参数,就象函数一样,例如: #define pr_debug(fmt,arg...) printk(KER ...

  2. c语言中的# ## 可变参数宏 ...和_ _VA_ARGS_ _

    1.#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串.例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字 ...

  3. 可变参数宏__VA_ARGS__

    在 GNU C 中,宏可以接受可变数目的参数,就象函数一样,例如:#define pr_debug(fmt,arg...) \printk(KERN_DEBUG fmt,##arg) 用可变参数宏(v ...

  4. 嵌入式C语言自我修养 12:有一种宏,叫可变参数宏

    12.1 什么是可变参数宏 在上面的教程中,我们学会了变参函数的定义和使用,基本套路就是使用 va_list.va_start.va_end 等宏,去解析那些可变参数列表我们找到这些参数的存储地址后, ...

  5. C函数和宏中的可变参数

    一:调用惯例 函数的调用方和被调用方对函数如何调用应该有统一的理解,否则函数就无法正确调用.比如foo(int n, int m),调用方如果认为压栈顺序是m,n,而foo认为压栈顺序是n, m,那么 ...

  6. C# 中的可变参数方法(VarArgs)

    首先需要明确一点:这里提到的可变参数方法,指的是具有 CallingConventions.VarArgs 调用约定的方法,而不是包含 params 参数的方法.可以通过MethodBase.Call ...

  7. Java中的可变参数以及foreach语句

    Java中的可变参数的定义格式如下: 返回值类型  方法名称(类型 ... 参数名称){} foreach语句的格式如下: for ( 数据类型  变量名称 :数据名称){ ... } public ...

  8. 【转】C,C++中使用可变参数

    可变参数即表示参数个数可以变化,可多可少,也表示参数的类型也可以变化,可以是 int,double还可以是char*,类,结构体等等.可变参数是实现printf(),sprintf()等函数的关键之处 ...

  9. 关于Retrofit网络请求URL中含有可变参数的处理

    开题:在此默认各位看官对Retrofit.以及Okhttp已经有过一定的了解及应用,所以今天我们不谈基础入门的东西,今天我们谈在Retrofit请求接口管理类中URL参数含有动态参数的处理方式.一般我 ...

随机推荐

  1. ECDSA host key for 192.168.0.101 has changed and you have requested strict checking.

    原文地址:http://blog.csdn.net/ausboyue/article/details/52775281 Linux SSH命令错误:ECDSA host key "ip地址& ...

  2. latex中使用定理、证明、缩进

    1.定理和证明 \documentclass[a4paper,UTF8]{article} \usepackage{ctex} \usepackage{amsthm,amsmath,amsfonts, ...

  3. Vue基础之数据绑定

    我们学习一门新语言或者框架时,第一件事是什么呢,那必然是向世界say Hello. 创建一个Vue应用 话不多说,先上代码,让我们感受一下Vue的核心功能 <!DOCTYPE html> ...

  4. linux下lampp的启动和停止脚本

    今天试着写了lampp的启动停止脚本,和上一篇的tomcat的启动停止有一点小区别,就是lampp启动之后有很多的进程号,如果按照tomcat的停止脚本写就会出错,下面做细细的介绍 1.lampp的停 ...

  5. hql和sql的一些区别

    日期格式化查询的区别: selectSql.append(" AND DATE_FORMAT(o.createDate,\'%Y-%m-%d\') = :createDate"); ...

  6. C++ 实验3 类和对象

    Part 2 #ifndef GRAPH_H #define GRAPH_H class Graph { public: Graph(char ch, int n); void draw(); pri ...

  7. [USACO06JAN]树林The Grove

    树木(grove)Time Limit: 1Sec Memory Limit: 64 MB[Description]牧场里有一片树林,林子里没有坑.贝茜很想知道,最少需要多少步能围绕树林走一圈,最后回 ...

  8. http和https区别及概念

    HTTP:是互联网上的应用广泛的一种网络协议,是一个客户端和服务器端请求和应答的传输协议,它可以使浏览器更加高效,使网络传输减少. HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版, ...

  9. 关于 legend_noa

    真名:qlw 性别:男 常用ID:legend_noa(有时候也用fseject以表示我的弱, 曾经不懂事用goddess_Q),具体意思是我最喜欢的两个奥特曼:诺亚和雷杰多 p1 诺亚,p2 雷杰多 ...

  10. python如何输出文件的年月日

    import time print('{}BiasedMF312and4414_rt.txt'.format(time.strftime("%Y-%m-%d"))) 输出: 201 ...