C语言中的可变量参数是通过将函数实现为可变参数的形式,可以使得函数可以接受1个以上的任意多个参数(不固定)。
举个例子解析一下:
实现一个函数可以求任意个参数的平均值
源代码:
//实现一个函数可以求任意个参数的平均值
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
int average(int n,...)
{
va_list arg;
int sum = 0;
int i = 0;
va_start(arg, n);
for (i = 0; i < n; i++)
{
sum += va_arg(arg, int);
}
va_end(arg);
return sum / n;
}
int main()
{
int ret = average(3, 3, 4, 5);
printf("%d\n", ret);
ret = average(4, 3, 4, 5, 8);
printf("%d\n", ret);
system("pause");
return 0;
}
下面逐句分析一下:
//实现一个函数可以求任意个参数的平均值
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
int average(int n,...)//可变参数列表用...表示
{
va_list arg;
//typedef char * va_list;为了区分,在这里将char*类型重定义为va_list,其实就是char*类型-->char* srg;
int sum = 0;
int i = 0;
//初始化arg为未知参数列表的第一个参数的地址
va_start(arg, n);
//#define va_start _crt_va_start
//#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
//arg = ((va_list)_ADDRESSOF(n) + _INSIZEOF(n))
//arg = ((char*)&n+4)-->找到n的位置,然后再找到未知参数的位置
for (i = 0; i < n; i++)
{
sum += va_arg(arg, int);
//#define va_arg _crt_va_arg
//#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
//sum += (*(int *)((arg += _INTSIZEOF(int)) - _INTSIZEOF(int)))
//sum += (*(int *)((arg += 4) - 4))-->将arg地址改变为下一个数的地址,但是留下来的是此地址,最后强制类型转换将数加上去,依次循环
}
va_end(arg);
//#define va_end _crt_va_end
//#define _crt_va_end(ap) ( ap = (va_list)0 )
//arg = (char*)0;
//arg始终维护的是未知参数列表中未知参数的位置,现在没用了,就赋值为空指针
return sum / n;
}
int main()
{
int ret = average(3, 3, 4, 5);
printf("%d\n", ret);
ret = average(4, 3, 4, 5, 8);
printf("%d\n", ret);
system("pause");
return 0;
}
这个变量是调用va_ start 来初始化的。它的第一个参数是va_ list的变量名,第2个参数是省略号前最后一个有名字的参数。初始化过程把arg变量设置为指向可变参数部分的第一个参数。
为了访问参数,需要使用va_ arg,这个宏接受两个参数 : va_.list变量和参数列表中下一个参数的类型。在这个例子中所有的可变参数都是整型。va_ arg 返回这个参数的值,并使用va_ arg指向下一个可变参数。
最后,当访问完毕最后一个可变参数之后,我们需要调用va_ end。
我们发现,由于可变量参数列表中的元素是未知的,所以在使用可变参数的时候有很多的限制。
案例实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
int MAX(int n, ...)
{
va_list arg;
int max = 0;
int i = 0;
va_start(arg, n);
max = va_arg(arg, int);//假设第一个值是最大的
for (i = 1; i < n; i++)
{
int tmp = va_arg(arg, int);
if (tmp>max)
{
max = tmp;
}
}
return max;
}
int main()
{
int max = MAX(4, 5, 6, 4, 2);
printf("max = %d\n", max);
system("pause");
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
void show(int num)
{
if (num > 9)
{
show(num / 10);
}
putchar(num % 10 + '0');
}
void print(char *format, ...)
{
va_list arg;
va_start(arg, format);
while (*format)
{
switch (*format)
{
case 's':
//字符串
{
char *ret = va_arg(arg, char*);
while (*ret)//循环打印出来
{
putchar(*ret);
ret++;
}
}
break;
case 'd':
//整型
{
int ret = va_arg(arg, int);
show(ret);//转化为字符打印
}
break;
case 'c':
//字符
{
putchar(va_arg(arg, char));
break;
}
default:
putchar(*format);
break;
}
format++;//遇到空格,此次类型结束,需要往后移动
}
}
int main()
{
print("s d c\n", "hello", 520, 'x','i','a');
print("s ccc d\n", "hello", 'b', 'i', 't',100);
system("pause");
return 0;
}