可变参数列表详解
来源:互联网 发布:苹果清除app缓存数据 编辑:程序博客网 时间:2024/06/05 17:41
一、定义及表达方式
可变参数,顾名思义,其参数是可变的,具体指的是其参数的个数是可变的,即函数参数数目可变,其一般格式为:
type VarArgFunc(type FixedArg1, type FixedArg2,...)
其中,参数可分为两部分:数目固定参数和数目可变参数。函数至少需要一个固定参数,固定参数的声明和普通参数一样,可变参数由于个数不确定,声明时用“…”表示。注意,固定参数和可变参数共同构成参数列表。
二、编写可变函数准备知识
要使用可变函数,需要引入头文件 #include “stdarg.h” ,要使用可变函数,需要先认识几个宏定义:
下面,具体看看这几个宏定义在VS2008中的内容:
//定义一个指向个数可变的参数列表typedef char* va_list; //定义va_list 是一个字符指针
可以看出,va_list arg的作用等同于char* arg。
//使参数列表指针ap指向函数参数列表中的第一个可选参数#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )//其中_INTSIZEOF(v)是指如果v是1,2,3,4个字节,则返回为4,如果为5,6,7.8个字节,则返回为8,类似于整型提升的作用//v为可变参数的的前一个参数,取出该参数的地址,并对其做地址的提升,指向下一个参数(即指向第一个可变参数)
可以看出,va_start(arg,n)是使参数列表指针arg指向函数参数列表中的第一个可选参数。
//返回参数列表中指针ap所指的参数,返回类型为type,并使指针p指向参数列表中的下一个参数#define va_arg(ap,t) (*(t *) ((ap +=_INTSIZEOF(t))-_INTSIZEOF(t)))
//清空参数列表,并置参数指针ap无效#define va_end(ap) (ap = (va_list)0 )
三、实例说明
下面,让我们以一个求任意个参数的平均值的函数为例:
#include <stdio.h>#include <stdarg.h>int average(int n, ...){ va_list arg; int i = 0; int sum = 0; va_start(arg, n); for(i=0; i<n; i++) { sum += va_arg(arg, int); } sum = sum/n; va_end(arg); return sum;}int main(){ int a = 4; int b = 5; int c = 7; int avg1 = average(2, a, c); int avg2 = average(3, a, b, c); printf("avg1 = %d\n", avg1); printf("avg2 = %d\n", avg2); return 0;}
函数先出main()函数开始运行,执行到int avg1 = average(2, a, c);时调用average(int n, …),将实参2传给形参n,此时函数的栈帧如下图所示:
进入average函数后,先执行va_list arg;定义一个char*的变量arg,接着定义两个临时变量,在执行下一步:
va_start(arg, n);//这句话定义为( arg = (va_list)&n + _INTSIZEOF(n) )//取出n的地址,并使arg指向n一个下一个地址,即指向a。(此时arg指向a)
接着循环求和n次:
sum += va_arg(arg, int);//va_arg(arg, int)表示:(*(int *) ((arg +=_INTSIZEOF(int))-_INTSIZEOF(int)))//sum += (*(int *)((arg += 4)-4))//每次拿到arg所指向的内容,并使arg向下偏移一个地址,为下次取内容做准备
求和之后,将其平均值赋给sum。
va_end(arg); //清空参数列表,并置参数指针arg无效
最后将sum返回。average函数调用完毕,完成对average函数的栈帧进行清栈。程序返回main()函数继续执行。
最后,小结一下,可变参数的函数就是:通过va_start初始化参数列表,然后使用va_arg从参数列表中取出你想要的参数,最后调用va_end执行清理工作。
4 0
- 详解可变参数列表
- 详解可变参数列表
- 详解可变参数列表
- 可变参数列表详解
- 详解可变参数列表
- 可变参数列表详解
- 【C语言】详解可变参数列表
- C语言可变参数列表详解
- Java可变参数列表
- 可变参数列表
- 关于可变参数列表
- 可变参数列表
- c++ 可变参数列表
- 可变参数列表
- cstdarg可变参数列表
- 可变参数列表
- java可变参数列表
- 可变参数列表
- Session ID/session token 及和cookie区别
- 设计模式->创建型模式->建造者模式
- /bin、/sbin、/usr/bin、/usr/sbin 目录所放置的执行文件区别
- js中splice对数组的操作
- 图像处理 去模糊 去马赛克 软件
- 可变参数列表详解
- 用贪心算法背包问题,Java实现
- C语言小白归并排序
- Python 数字对象
- XMU 1613 刘备闯三国之三顾茅庐(一) 【并查集】
- WPF多线程UI更新——两种方法
- eclipse上安装spring tool suite插件的过程记录
- wilddog & arcgisAPI & vue-cli插件,天坑之路(三)
- LeetCode119. Pascal's Triangle II