博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C和C++中的不定参数
阅读量:4364 次
发布时间:2019-06-07

本文共 1828 字,大约阅读时间需要 6 分钟。

在初学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
#include
#include
int sum(int count, ...);int main(){ int nS = sum(3,1,2,3); printf("%d\n", nS); return 0;}int sum(int count, ...){ int _sum,arg,i; va_list arg_ptr; _sum = 0; va_start(arg_ptr,count); for(i=0; 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)

转载于:https://www.cnblogs.com/fnlingnzb-learner/p/6401833.html

你可能感兴趣的文章
CSS学习
查看>>
Centos 安装lnmp完整版
查看>>
【转】Eclipse和PyDev搭建完美Python开发环境(Ubuntu篇)
查看>>
Differences between page and segment
查看>>
字符串之strcmp
查看>>
最长公共子序列(不连续)
查看>>
微服务:Java EE的拯救者还是掘墓人?
查看>>
如何在Centos里面,把.net core程序设为开机自启动
查看>>
1920*1080pc端适配
查看>>
Nutch系列1:简介
查看>>
前端UI框架选择区别对比推荐
查看>>
栈 队列 和 双向队列
查看>>
从垃圾回收看闭包
查看>>
Intel Core Microarchitecture Pipeline
查看>>
如何去除交叉表的子行(列)的小计?
查看>>
Web字体(链接)嵌入
查看>>
switch… case 语句的用法
查看>>
day07补充-数据类型总结及拷贝
查看>>
语言、数据和运算符
查看>>
正则表达式30分钟入门教程
查看>>