可变参数列表步骤的常规介绍
在我们平常使用可变参数列表的过程中,通常需要以下几条指令来完成功能,首先我们把这几条命令结合系统的定义来解读一下。
1.首先是va_list这个命令,等价于char*,* 为了后面的内容便于理解,这里我们需要在char的后面加入一个被创建的指针arg,也就是char*p,最原始的形态就是va_list p;
2.接下来是va_start的功能,,是通已知的参数来让指针指向未知参数的第一个数。va_start中需要放入两个变量,分别是上面va_list中创建的指针p和整个函数中接收的已知形参中的最后一个。
3.在va_arg(p,int)中实现。这里表示把p向后跳sizeof(int)的大小,指向下一个参数,返回的是当前参数,但ap指针此时指向的已经是下一个参数了。
4最后就是va_end(p),这个是结束的标志,把p改为空指针。
实际操作中使用可变参数列表、
接下来我们试一试使用可变参数列表来求几个可变参数的平均值。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdarg.h>
int average(int n, ...)
{
va_list p; //这里就是创建了字符指针p
va_start(p, n); //指针p跳过n指向了未知参数的第一个
int i = 0;
int sum = 0;
for (i = 0; i < n; i++)
{
sum += va_arg(p, int);//返回当前参数,指针指向下一个
} //参数
return sum / n;
va_end(p); //结束标志
}
int main()
{
int a = 1;
int b = 12;
int c = 8;
int d = 5;
int avg1 = average(3, a, c, d);
int avg2 = average(2,b,d);
printf("%d \n",avg1);
return 0;
}
程序运行结果如下图所示:
通过上面的简单练习就可以简单发现可变参数列表的使用是有规律的而且非常易懂的。
实际原理
- va_list
typedef char * va_list; //字符指针类型
- va_start(p,type)
#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))//ap指向下一个参数,lastarg不变
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) //跳过下第一个参数,指向第二个参数内存地址
#endif
//对type向上取整 取int的整 4,然后乘上int整型4的倍数
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
- va_arg(p,int)
#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))//ap指向下一个参数,lastarg不变
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) //跳过下第一个参数,指向第二个参数内存地址
#endif
//对type向上取整 取int的整 4,然后乘上int整型4的倍数
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
- va_end(p)
#define _crt_va_end(p) ( p = (va_list)0 )
把p化为空指针。