可变参数列表

来源:互联网 发布:卖时时彩源码违法吗 编辑:程序博客网 时间: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;}





2 0
原创粉丝点击