在C语言的标准库中,printf、scanf、sscanf、sprintf、sscanf这些标准库的输入输出函数,参数都是可变的。在调试程序时,我们可能希望定义一个参数可变的输出函数来记录日志,那么用可变参数的宏是一个不错的选择。

在C99中规定宏也可以像函数一样带可变的参数,如:

#define LOG(format, ...) fprintf(stdout, format, __VA_ARGS__)

其中,...表示可变参数列表,__VA_ARGS__在预处理中,会被实际的参数集(实参列表)所替换。

同时gcc还支持带可以变参数名的方式(注意:VC不支持):

#define LOG(format, args...) fprintf(stdout, format, args)

同样,args在预处理过程中,会被实际的参数集所替换。其用法和上面的方式一样,只是参数的符号有变。

需要注意的是,上述两种方式的可变参数不能省略,尽管可以传一个空参数进去。说到这里,有必要提一下“##”连接符号的用法,“##”的作用是对token进行连接,上例中format,args,__VA_ARGS都可以看作是token,如果token为空,“##”则不进行连接,所以允许省略可变参数。对上述2个示例的改造:

#define LOG(format, ...) fprintf(stdout, format, ##__VA_ARGS__)
#define LOG(format, args...) fprintf(stdout, format, ##args)

即然参数可以省略,那么用宏定义一个开关,实现一个输出日志的函数就简单了:

#ifdef DEBUG
#define LOG(format, ...) fprintf(stdout, ">>>>>" format "<<<<", ##__VA_ARGS__)
#else
#define LOG(format, ...)
#endif

example

#include "stdio.h"

#define LOG_TYPE1(format, ...) do{ 		\
printf(format, __VA_ARGS__); \
\
} while(0) #define LOG_TYPE2(format, args...) do{ \
printf(format, args); \
\
} while(0) #define LOG_TYPE3(format, ...) do{ \
printf(format, ##__VA_ARGS__); \
\
} while(0) #define LOG_TYPE4(format, args...) do{ \
printf(format, ##args); \
\
} while(0) #define LOG(x) printf("LOG "#x" %d \n", x); int value = 10; int main()
{ printf("hello world. \n"); //LOG_TYPE1("hello %d \n"); error
LOG_TYPE1("hello %d \n", 1); //LOG_TYPE2("hello \n"); error
LOG_TYPE2("hello %d \n", 2); LOG_TYPE3("hello 3\n");
LOG_TYPE3("hello %d\n", 3); LOG_TYPE4("hello 4\n");
LOG_TYPE4("hello %d\n", 4); LOG(10);
LOG(value); return 0;
}

C 语言 define 变参__VA_ARGS__使用的更多相关文章

  1. C语言可变参实现参数累加返回

    C语言可变参的作用真的是非常大,自从发表了可变参如何实现printf,fprintf,sprintf的文章以来,便有不少博友私信问我实现的机制,我也解释了相关的知识点.今天,我们借着这个机会,再来举一 ...

  2. c语言可变参

    一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ...

  3. C语言-define 与do{}while(0)

    问题引出: 我们都知道宏定义#define只是简单替换,所以遇到复杂的带参数宏,必须很小心的为需要的参数加上括号“()”:同样碰到复杂的多条语句替代,虽然加{}可以将其封装成一个整体,但同时又有另一个 ...

  4. c语言#define用法

    01 作用域 预编译作用域限本文全局,如: a.c中定义:#define TEST 1 b.c中定义:#define TEST 2 两者编译不交叉,互不影响. 若需#define TEST作用于a.c ...

  5. C语言define 可以提高程序运行的速度

    define的优缺点 优点 提高了程序的可读性,同时也方便进行修改: 提高程序的运行效率:使用带参的宏定义既可完成函数调用的功能,又能避免函数的出栈与入栈操作,减少系统开销,提高运行效率: 3.宏是由 ...

  6. c语言define和typedef区别和使用

    define完全可以理解替换,typedef代表别名.听着差不多的意思,那2者区别在哪? 先来个简单例子查看基本使用. //define和typedef区别 #define DB double //替 ...

  7. C语言 define实现的宏函数汇总

    最大值,最小值 #define MAX( x, y ) ( (x) > (y) ? (x) : (y) )#define MIN( x, y ) ( (x) < (y) ? (x) : ( ...

  8. C语言的变参列表 va_list

    1. va_list的基本原理和用法 #include<stdio.h> #include<stdarg.h> void func(int i,char *ch,...){ / ...

  9. 【C语言】中的版本规范(C89 C99等)

    C语言中的版本 一.相关基础知识 ISO:国际标准化组织(International Organization for Standardization,ISO)简称ISO,是一个全球性的非政府组织,是 ...

随机推荐

  1. git分支管理之Bug分支

    软件开发中,bug就像家常便饭一样.有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除. 当你接到一个修复一 ...

  2. 安徽省2016“京胜杯”程序设计大赛_B_阵前第一功

    阵前第一功 Time Limit: 1000 MS Memory Limit: 65536 KB Total Submissions: 63 Accepted: 29 Description A国每个 ...

  3. RabbitMQ入门与使用篇

    介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue)协议的开源实现.用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面都非常的优秀 ...

  4. Qt支持中文显示

    Qt支持中文显示<1>.在代码中添加以下代码 QTextCodec* codec = QTextCodec::codecForLocale(); if (codec != NULL) { ...

  5. WSGIweb框架--1

    from multiprocessing import Process import re import sys import socket #设置静态文件根目录 HTML_ROOT_DIR = '. ...

  6. Entity Framework - 基于外键关联的单向一对一关系

    代码的世界,原以为世界关系很简单,确道是关系无处不在.NET世界里ORM框架中EntityFramework作为其中翘楚,大大解放了搬砖工作的重复工作,着实提高了不少生产力,而也碰到过不少问题!比如关 ...

  7. led模组的优点和却点

    插件模组 1.是指DIP封装的灯将灯脚穿过PCB板,经由过程焊接将锡灌满在灯孔内,由这种工艺做成的LED模组便是插灯模组:益处是视角年夜,亮度高,散热好:谬误舛错是像素密度小. 表贴模组 1.表贴也叫 ...

  8. Python 中的重点来了 : 迭代器 生成器

    可迭代的对象:带有__iter__方法的,就是迭代器.字符串,列表,元祖,字典,集合,文件,都是可迭代的 可迭代的对象使用了__iter__方法的,就是迭代器,带有__next__,__iter__方 ...

  9. Andrew Ng机器学习课程笔记--week8(K-means&PCA)

    Unsupervised Learning 本周我们讲学习非监督学习算法,会学习到如下概念 聚类(clustering) PCA(Principal Componets Analysis主成分分析), ...

  10. 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...