~欢迎你!第 AmazingCounters.com 位造访者

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无疑会更方便一点。

posted @ 2018-08-28 20:00  ~HDMaxfun  阅读(421)  评论(0编辑  收藏  举报