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无疑会更方便一点。
C语言可变参数的更多相关文章
- 转:C语言 可变参数
C语言 可变参数 堆栈一般是怎么压栈处理的 /* * stack space: * * 参数3 | up * 参数2 | * 参数1 v ...
- C语言 可变参数
一.基础部分 1.1 什么是可变长参数 可变长参数:顾名思义,就是函数的参数长度(数量)是可变的.比如 C 语言的 printf 系列的(格式化输入输出等)函数,都是参数可变的.下面是 printf ...
- C语言可变参数函数实现原理
一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本 ...
- 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)
一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ...
- C语言可变参数在宏定义中的应用
在C语言的标准库中,printf.scanf.sscanf.sprintf.sscanf这些标准库的输入输出函数,参数都是可变的.在调试程序时,我们可能希望定义一个参数可变的输出函数来记录日志,那么用 ...
- C语言可变参数函数的编写
1. 引言 C语言我们接触的第一个库函数是 printf(“hello,world!”);其参数个数为1个. 然后,我们会接触到诸如: printf(“a=%d,b=%s,c=%c”,a,b,c);此 ...
- C语言可变参数va_list
一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,-) int ...
- c语言可变参数函数
c语言支持可变参数函数.这里的可变指,函数的参数个数可变. 其原理是,一般情况下,函数参数传递时,其压栈顺序是从右向左,栈在虚拟内存中的增长方向是从上往下.所以,对于一个函数调用 func(int a ...
- Go语言 可变参数
最近与同事讨论时,提到Go语言的可变参数,之前没有总结过相关知识点,今天我们介绍一下Go语言的可变参数. 可变参数(Variable Parameters):参数数量可变的函数称之为可变参数函数,主要 ...
随机推荐
- IDEA (mac版)
mac键:option=alt command=ctrl idea快捷键 command+Enter(get,set界面) command+alt+L (格式化代码) ctrl+shift+space ...
- HDU-1028 Ignatius and the Princess III(生成函数)
题意 给出$n$,问用$1$到$n$的数字问能构成$n$的方案数 思路 生成函数基础题,$x^{n}$的系数即答案. 代码 #include <bits/stdc++.h> #define ...
- Java Socket 服务端发送数据 客户端接收数据
服务端: package com.thinkgem.wlw.modules.api.test.socket; /** * @Author: zhouhe * @Date: 2019/4/8 9:30 ...
- C#调用Bartender打印
BarTender是一款优秀的条形码打印软件,可以支持很多种类型的条形码设计和打印,具体大家可参考他的官网(http://www.seagullscientific.com/aspx/products ...
- XSS,CSRF,Cookie防劫持的处理
Cookie与sessionHTTP天然是无状态的协议, 为了维持和跟踪用户的状态, 引入了Cookie和Session. Cookie包含了浏览器客户端的用户凭证, 相对较小. Session则维护 ...
- C语言通讯录系统——C语言单向链表实现
实现的通讯录功能有:查看通讯录.添加联系人.删除联系人.查询联系人.保存并退出. 通过txt文件保存和读取通讯录数据. #include <stdio.h> #include <st ...
- C# - 设计模式目录
什么是设计模式 设计模式(OOD)是在面向对象编程(Object Oriented Programming,OOP)中针对在以往的编程里出现的问题所提出的一种解决思路.一种设计类型时的思想和经验,对未 ...
- 手把手使用Git?
下载和安装:Git下载和安装教程 学习使用Git:学习Git 安装TortoiseGit:教程 TortoiseGit与Git生成SSH密钥添加到GitHub账号的简单方法:解决方法
- ABP架构学习系列四:集成Dapper
之前,一直想集成Dapper到项目中,但是一直没成功,今天把abp升级到最新版,然后按教程来,就可以了,呵呵 现在,基于上一篇的源码进行升级和集成dapper,将abp升级到3.8.2 官方 ...
- 【easy】107. Binary Tree Level Order Traversal II 按层输出二叉树
按层输出二叉树,广度优先. 3 / \ 9 20 / \ 15 7 [ [15,7], [9,20], [3] ] /** * Definition for a binary tree node. * ...