在初学C的时候,我们都会用到printf函数来写Hello World的程序.在我们看printf函数的声明时,会看到类似于下面代码

int     printf(const char * __restrict, ...);

另外,在我们学习C和C++的时候,函数的声明总是确定个数和类型的,而我们在用printf的时候,却可以一次输出多个参数.

这就是我们要提的不定参数了.

在32位的C和C++编程中,函数调用是有规约的,并且各个编译器也基本达成了一致,尽管他们编译出的东西基本不能通用.关于调用规约的东西,可以参考一下维基百科.

在64位的C和C++编程中,就没有调用规约的概念了,基本上做到了统一,但是不同的编译器的传参方式却不尽相同,这里我们不去讨论了,有兴趣的可以编译到汇编代码查看.

不定参数的函数调用方式为cdec方式的,也就是由调用者来恢复参数栈,这个不难理解,因为被调用的函数无从得知有多少个参数传进来,所以不可能知道如何恢复栈.

如果上面写的你看不懂,不要紧,你可以用google搜一下,相信很快你就会明白了,不搜也不要紧.

在使用不定参数时,我们会用到三个宏,分别是

va_start , va_arg 和 va_end

还有一个类型 va_list

它们都定义在 stdarg.h 或者 cstdarg (C++)里,使用时记得引入.

其中,va_start用来用于初始化va_list, va_arg用来读取va_list中的参数,当所有的读取都结束后要用va_end来释放va_list.

下面写一个示例

#include<stdlib.h>
#include<stdio.h>
#include<stdarg.h>
int sum(int count, ...);
int main()
{
int nS = sum(,,,); printf("%d\n", nS);
return ;
}
int sum(int count, ...)
{
int _sum,arg,i;
va_list arg_ptr;
_sum = ;
va_start(arg_ptr,count);
for(i=; i < count; ++i)
{
arg = va_arg(arg_ptr,int);
_sum += arg;
}
va_end(arg_ptr);
return _sum;
}

上面的例子比较简单,后续参数个数由第一个参数指定,而且类型默认都是int类型的.

在printf函数中,后续参数个数是由第一个格式字符串来指定的,并且指定了参数类型,比如%d 说明对应的参数是整形而%f 对应的是浮点类型.

接下来我们看看这几个宏.

va_start是用来初始化va_list的,第一个参数是参数表的指针,第二个参数是不定参数前的最后一个参数.

va_arg 是用来读取不定参数,第一个参数是参数表的指针,第二个参数是参数的类型.函数本身并不知道参数的类型,所以使用不当会导致出错.

va_end是用来释放va_list占用的资源的,只有一个参数,就是要释放的va_list.

最后,我们通过printf函数来总结一下使用不定参数的一些规范:

1. 函数本身必须有办法知道不定参数的类型,比如printf通过格式化字符串通知函数后续参数的每个参数的类型,其中的%d类形的格式与后续的参数是一一对应的.在我写的示例代码中,是默认约定了所有参数都是int 类型的.

2. 函数必须能知道参数结束的地方,printf函数是由格式输出字符串来知道的,当没有类似%d或%f 这种字符出现时,参数就结束了.我给出的例子中,是通过第一个参数给定了后续参数的个数的.

3.调用必须严格按照调用的约定来做,而且不定的参数是不会自动转型的,比如当我们 printf("%d",3.3) 会发现输出的不是3,就是因为3.3作为一个浮点数传入,而不会因为格式字符串中的%d自动转成整数.要想得到预期的结果,需要写成下面这样 printf("%d",(int)3.3)

C和C++中的不定参数的更多相关文章

  1. C++ 中的不定参数与格式化字符串 # ## vsprintf

    日志打印或者格式字符串时,可能会用到不定参数的使用,这里记录一下. 格式化字符串有很多方法: snprintf std::stringstream # ##的使用 ##是一个连接符号,用于把参数连在一 ...

  2. Objective-C中使用不定参数个数的方法调用

    Objective-C中,定义并使用带有不定参数个数的对象方法与C函数类似,规则上也要求不定参数列表中必须至少要有一个形参,然后参数列表的最后跟省略号表示不定参数.省略号不能放在参数当中部分,只能放在 ...

  3. python 常见包中的不定参数

  4. golang中不定参数与数组切片的区别

    package main import "fmt" func main() { myfunc1(, , , ) //传递不定数量的参数 myfunc2([], , , }) //传 ...

  5. 深入浅出ES6(五):不定参数和默认参数

    作者 Jason Orendorff  github主页  https://github.com/jorendorff 不定参数 我们通常使用可变参函数来构造API,可变参函数可接受任意数量的参数.例 ...

  6. C语言函数不定参数实现方式

    函数如何实现不定参数: 由于在C语言中没有函数重载,解决不定数目函数参数问题变得比较麻烦,即使采用C++,如果参数个数不能确定,也很难采用函数重载.对这种情况,提出了指针参数来解决问题. (1)va_ ...

  7. [js高手之路] es6系列教程 - 不定参数与展开运算符(...)

    三个点(...)在es6中,有两个含义: 用在形参中, 表示传递给他的参数集合, 类似于arguments, 叫不定参数. 语法格式:  在形参面前加三个点( ... ) 用在数组前面,可以把数组的值 ...

  8. SE6 不定参数和默认参数详解和使用细节

    在SE5以前我们通常通过arguments类数组对象来引用不定形参,SE6则使用了一种叫做不定参数的写法,比起隐式的arguments要直观的多. 不定参数使用...参数名来指定一个不定参数,参数名指 ...

  9. dataframe的select传入不定参数

    在提取 dataframe 里面的列时,需要传入不定参数,即 dataframe.select(args) .例如某个 dataframe 如下: 一般提取某列或者某几列的时候是这样子写的: data ...

随机推荐

  1. 使用 某款基于Socks5协议的代理软件 一段时间后 被封锁掉IP的一些技术思考

    由于关键词比较敏感为了不被删除帖子所以文中某软件(上图所示软件)不用全称表示. 去年9月末在 在某国外网站 上弄了一个vpn,在上面安装了某软件,使用起来还是蛮不错的,平时查查英文论文,看看美剧还是比 ...

  2. PyQt4 HardwareManager

    # PyQt4 HardwareManager # 声明: # 本软件主要是由于朋友说想要一个产品缺陷记录软件,主要用于记录产品缺陷, # 通过产品序列号进行插入.查询,本来想用VC++ 6.0做,但 ...

  3. MySQL-with rollup函数运用

    如果想在下面这个表下面添加一行 总计 数据行SQL代码怎么实现 并且根据9月金额进行城市降序 总计置于底部呢 MySQL提供了 group by with rollup 函数进行group by 字段 ...

  4. Phonegap 自定义插件

    一.PhoneGap中js与Java之间相互调用分为同步和异步两种方式 1.同步:js调用Java类的方法,然后Java类的方法直接返回一个值给js端 2.异步:js调用Java类的方法,Java类的 ...

  5. windows mac ssh 出国访问google等系列网站

    淘宝买ssh代理 windows:tunnelier mac:issh 浏览器:chrome  插件:switchysharp

  6. 【free() invalid next size】谨慎地在C++的类中存储指针来方便访问其他节点

    “我跟你们说,你们知道STL容器,vector/string/deque等等,都有个reserve方法吗?你们一个个地push_back,嫌C++比C慢,怪谁?” “要像我这样,预先分配足够大的空间, ...

  7. FastDFS简介和安装

    FastDFS是一个轻量级的开源分布式文件系统 FastDFS主要解决了大容量的文件存储和高并发访问的问题,文件存取时实现了负载均衡 FastDFS实现了软件方式的RAID,可以使用廉价的IDE硬盘进 ...

  8. 黄聪:WordPress 多站点建站教程(二):后台(管理网络)设置详解,如何管理子站的用户、主题、插件、设置等功能

    建立好了子站,我们需要有个地方配置所有子站的主题.插件等功能,我们可以在后台看到 我的站点--管理网络 如下图: 在 管理网络--仪表盘 里面,我们可以创新用户和站点,也提供了查询功能. 要注意的是: ...

  9. 腾讯高性能RPC开发框架Tars实现服务治理(微服务)

    Github:https://github.com/Tencent/Tars 1. 介绍 Tars是基于名字服务使用Tars协议的高性能RPC开发框架,同时配套一体化的服务治理平台,帮助个人或者企业快 ...

  10. bzoj 4885: [Lydsy2017年5月月赛]长方体

    Description 给定一个a*b*c的长方体,定义其表面上两个点的距离为沿着长方体的表面走的最短路径的长度,请找到距离最远的点对,你需要保证找到的两个点里至少有一个是长方体顶点. Input 第 ...