C语言可变参数
前段时候在实现利用redis进行的一个数据库比对的功能,稍微去分析了一下redis里面的源代码,然后发现其中的发送命令接口声明如下:
void *redisCommand(redisConnect *c,const char * Format,...);
其中使用了我以前没有见过的 "..." ,想起之前学习java视频的时候,好像提到过java的可变参数功能,于是就去网上查阅了一下,发现可变参数也是C语言提供的一个功能。
关于功能的应用场景我举两个例子吧:
第一个就是上面的这个函数声明,在redis中上面这个函数功能就是向指定的 redisconnect连接发送句柄的。redisconnect存的是redis连接的端口,Fromat存的指令句柄,后面的"..."则使得这个函数可以支持一次性传如多个指令:
reply = (redisReply *)redisCommand(context, cmd); reply = (redisReply *)redisCommand(context, cmd, cmd2, cmd3);
第一行代码,很容易理解,就是通过语句传入cmd句柄让redis执行cmd句柄中的语句。
第二行代码,则让redis依次执行cmd,cmd1,cmd2三个句柄。
在这个样例中,我们可以通过一个接口一次性传入未知的参数量,也可以避免重复调用接口、建立连接,或者要更新函数、重载函数。
具体如何实现多个句柄传入我们不妨先看看场景二。
第二个场景其实就更常见了,可以看一下我下面这段代码:
#include "cstdio"
#include "stdarg.h" void pt(const char* format, ...) {
int n;
va_list arg_list;
va_start(arg_list, format);
n = vprintf(format, arg_list);
va_end(arg_list);
} int main(){
pt("%d , %d , %d , %d\n",1,2,3,4);
return 0;
}
输出之后,你就会发现,这个pt()函数和我们平常用的printf()函数实现的功能一样!
是的,我们通过控制台读入和输出的scanf(),和printf()两个函数都使用了可变参数,这样也就解释了,为啥一个scanf()函数我们可以一次性输入不管多少个参数了。
可变参数!
C调用约定下可使用在stdarg.h这个头文件中的va_list系列变参宏实现变参函数,此处va意为variable-argument(可变参数)。
详情可以去博客进行了解:https://www.cnblogs.com/clover-toeic/p/3736748.html
后面了解到在C++中使用可变参数有另外的一种方法:
void debug() {
cout << endl;
}
template<typename T, typename ...R> void debug (T f, R ...r) {
cout << " [" << f << "] ";
debug (r...);
}
上面这段代码可以在控制台输出你传递到debug()中的所有变量,不过使用的理念和C语言版本的不同。
C语言版本是把你传递进去的参数压入堆栈,然后用va_list系列的函数不断取出栈内的值。
而上面这段C++的代码,使用递归每次输出第一个参数,简明易懂。
虽然通常我们写代码一般是不会出现这种代码的,但是如果只是我们自己对代码进行debug的时候,这样写对我们进行debug无疑会更方便一点。
最新文章
- Android开机启动程序
- Golang友团无闻Go语言Web基础视频教程
- 二、Python 数据类型
- Integer Inquiry【大数的加法举例】
- 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
- delphi中Message消息的使用方法
- maven下载的jar文件出现invalid LOC header (bad signature)
- 基于Flume的美团日志收集系统(二)改进和优化
- Web 前端最佳实践
- jQuery moblie 配合jQuery 实现移动端下拉刷新
- VirtualBox的快照功能
- 十二、存token获取token刷新token发送header头
- go官方的http.request + context样例
- JSP(3)—Cookie和Session
- 12C新特性 -- 共享asm口令文件
- 在springboot中用redis实现消息队列
- hdu 5129 (枚举) The E-pang Palace
- lucene-01-简介
- c#版本与vs的对应关系
- 图解vim常用命令
热门文章
- 第30月第11天 Xcode 9.0中新增的API版本检查@available
- axios formData提交数据 &;&; axios设置charset无效???
- 【easy】141. Linked List Cycle
- 关于el-upload上传
- axios 拦截器统一在接口增加时间戳参数,防止走缓存。
- Nginx+IIS+asp.net mvc 实现负载均衡示例
- MiniGUI 如何显示繁体字
- 对Inode、Hard Link以及Soft Link的理解
- Log4j使用笔记:每天生成一个日志文件、按日志大小生成文件
- Python @property 详解