可变参数列表
来源:互联网 发布:卖时时彩源码违法吗 编辑:程序博客网 时间:2024/06/15 22:19
在函数原型中,列出了函数期望接受的参数,但函数只能显示固定数目的参数。让一个函数在不同的时候接受不同的数目的参数是不是可以呢?答案是肯定的(printf就是一个可变参函数),但存在一些限制。
int avarage(int val, int v1, int v2, int v3, int v4, int v5){float sum = v1;if (val >= 2)sum += v2;if (val >= 3)sum += v3;if (val >= 4)sum += v4;if (val >= 5)sum += v5;return sum / val;}
调用的时候avarage(3,1,2,3)
但是这样会有一个错误。
error C2660: 'avarage' : function does not take 3 parameters
为了解决上述的问题: C语⾔中引入了可变参数列表的概念。
stdarg宏
可变参数列表是通过宏来实现的,这些宏定义于stdarg.h头文件中,它是标准库的一部分。这个头文件声明 一个类型va_list 和三个宏va_start、va_arg和va_end。
我们可以声明一个类型为va_list的变量,与这几个宏配合使用,访问参数。
如下程序:
#include <stdarg.h>int avarage(int val, ...){va_list arg;int count;float sum = 0;//准备访问可变参数 va_start(arg, val);//添加取⾃可变参数列表的值 for (count = 0; count < val; count += 1){sum += va_arg(arg, int);}//完成处理可变参数 va_end(arg);return sum / val;}
声明一个va_list类型的变量arg,它用于访问参数列表的未确定部分。
这个变量是调用va_start来初始化的。它的第一个参数是va_list的变量名,
第2个参数是省略号前最后一个有名字的参数。
初始化过程把var_arg变量设置为指向可变参数部分的第一个参数。
为了访问参数,需要使用va_arg,这个宏接受两个参数:
va_list变量和参数列表中下一个参数的类型。
在这个例子中所有的可变参数都是整型。
va_arg返回这个参数的值,并使用var_arg指向下一个可变参数。
最后,当访问完毕最后一个可变参数之后,我们需要调用va_end。
可变参数的限制
注意,可变参数必须从头到尾逐个访问。如果你在访问了几个可变参数之后想半途终止,这是可以的,但是,如果你想一开始就访问参数列表中间的参数,那是不行的。
1.参数列表中至少有一个命名参数。如果连一个命名参数都没有,就无法使用va_start。
2.这些宏是无法直接判断实际存在参数的数量。
3.这些宏无法判断每个参数的是类型。
4.如果在va_arg中指定了错误的类型,那么其后果是不可预测的。
可变参数列表例题:
【一】实现求n个数中最大数
#include<stdio.h>#include<stdarg.h>int Max(int n, ...){va_list arg;int i;int max=0;//准备访问可变参数列表的值va_start(arg, n);//访问取自可变参数列表的值for (i = 0; i < n; i++){int val = va_arg(arg, int);if (val>max){max = val;}}//完成处理可变参数va_end(arg);return max;}int main(){int ret = Max(5, 12, 3, 45, 6, 2);printf("Max=%d", ret);system("pause");return 0;}
【二】求n个数的平均数
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<stdarg.h>float average(int n, ...){va_list arg;int i = 0;float aver = 0;va_start(arg, n);for (i = 0; i < n; i++){aver += va_arg(arg, int);}va_end(arg);return aver / n;}int main(){float ave = average(5, 5, 7, 9, 2, 3);printf("average=%f", ave);system("pause");return 0;}【三】模拟实现printf函数
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<stdarg.h>void my_printf(const char*str, ...){va_list arg;char c = 0;va_start(arg, str);while (c=*str++){switch (c){case 'd':{int d = va_arg(arg, int);putchar(d + '0');}break;case 'c':{char ch = va_arg(arg, char);putchar(ch);}break;case 's':{char* str = va_arg(arg, char*);fputs(str, stdout);}break;case '%':break;default:putchar(c);break;}}va_end(arg);}int main(){my_printf("%d\t%c\t%s\n", 1,'r',"abcdef");system("pause");return 0;}
- Java可变参数列表
- 可变参数列表
- 关于可变参数列表
- 可变参数列表
- c++ 可变参数列表
- 可变参数列表
- cstdarg可变参数列表
- 可变参数列表
- java可变参数列表
- 可变参数列表
- Java 可变参数列表
- 可变参数列表
- C可变参数列表
- 可变参数列表
- C可变参数列表
- 可变参数列表
- /可变参数列表
- 可变参数列表
- C# Dictionary
- boosting-bagging
- java中的static总结
- 分析mysql慢查询日志的好工具--mysqlsla
- HttpUrlConnection与HttpClient的认识(四) -HttpClient的封装
- 可变参数列表
- BZOJ 2326: [HNOI2011]数学作业
- 如何保护个人信息安全?
- 谈谈对Spring IOC的理解
- React Native系列之flexbox布局(伸缩属性)
- hive常见操作语句--创建表语句
- Intellij IDEA 出现“Usage of API documented as @since 1.6+”的解决办法
- STM32编译错误汇总(一)
- 【bzoj 3196】Tyvj 1730 二逼平衡树