可变参数列表概述
C语言中可变参数列表是通过宏来实现的,这些宏包含在stdarg.h
头文件中,该头文件定义了va_list类型和三个宏:va_start、va_arg、va_end。
可变参数列表用法(“一个类型,三个宏”)
1、首先声明一个va_list类型的变量,va_list是一个类型,定义一个该类型的变量arg,可以用该变量作为保存可变参数列表的指针。
2、使用va_start宏进行初始化,va_start宏的第一个参数是该va_list类型的变量,第二个参数是非可变参数的最后一个参数
3、访问可变参数时使用va_arg宏,该宏的第一个参数是va_list变量名,第二个参数是参数列表中下一个参数的类型。 va_arg宏返回该参数的值,并使变量指向下一个可变参数。
4、当访问完最后一个参数之后,需要调用va_end宏。
可变参数是有限制的
- 可变参数必须从头到尾逐个顺序的访问,可以访问几个变量后终止,但是不可以从一开始就访问中间的变量。
- 参数列表中至少要有一个命名参数,因为要使用va_start宏进行初始化。
- 这些宏无法判断实际存在参数的数量,这些宏无法判断每个参数的类型。
求平均值(使用可变参数列表)
在进行参数调用时,会从右到左吧参数压入到栈中,下面看看下边例子中的参数入栈情况:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
#include<stdarg.h>
int aver(int num, ...)
{
int i = 0;
int sum = 0;
va_list arg;
va_start(arg, num);
for (i = 0; i<num; i++)
{
sum = sum + va_arg(arg, int);
}
va_end(arg);
return sum / num;
}
int main()
{
printf("平均数是%d\n", aver(9, 3, 2, 1, 5, 6, 4, 8, 7, 10));
system("pause");
return 0;
}
求最大值 (使用可变参数列表)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
#include<stdarg.h>
int Max(int n,...)
{
int max=0;
int i=0;
va_list arg;
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()
{
printf("Max==%d\n",Max(10,99,88,77,66,55,4,3,2,1,20));
system("pause");
return 0;
}
模拟实现printf函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
#include<stdarg.h>
#include<assert.h>
void My_Print(char*type, ...)
{
va_list value;
va_start(value, type);
while (*type != '\0')
{
if (*type == 's')
puts(va_arg(value, char*));
else if (*type == 'c')
putchar(va_arg(value, char));
else if (*type == 'd')
{
int tmp = va_arg(value, int);
printf("%d\n", tmp);
}
type++;
}
va_end(value);
}
int main()
{
My_Print("s s d", "hello", "World!", 100);
system("pause");
return 0;
}
main函数可变参数应用----计算器
#include<iostream>
#include<stdlib.h>
using namespace std;
int main(int argc, char*argv[])
{
int num1=atoi(argv[1]);
int num2=atoi(argv[3]);
if(argc!=4){
cout<<"Usage:./a.out num1 a/s/m/d num2"<<endl;
}
switch(argv[2][0])
{
case 'a':
cout<<num1+num2<<endl;
break;
case 's':
cout<<num1-num2<<endl;
break;
case 'm':
cout<<num1*num2<<endl;
break;
case 'd':
cout<<num1/num2<<endl;
break;
}
return 0;
}