有一些函数希望能在不同的情况下接受一些数量不同的变量,比如说printf。
为了解决这样的问题,C语言引入了可变参数列表的概念!
可变参数的实现:
可变参数列表是通过宏来实现的,这些宏定义在stdarg.h头文件中。在这个头文件中,声明了一个类型va_list,和三个宏,va_start、va_arg、va_end。
①首先在函数里定义一具va_list型的变量,这个变量是指向参数的指针
②然后用va_stat宏初始化变量刚定义的va_list变量,va_start有两个参数,第一个参数是va_list声明的变量,第二个参数是省略号之前最后一个有名字的参数!
③然后用va_arg返回可变的参数,va_arg也有两个参数,第一个参数是va_list声明的变量,第二个参数是这个可变参数的类型。
④最后用va_end宏结束可变参数的获取。
③然后用va_arg返回可变的参数,va_arg也有两个参数,第一个参数是va_list声明的变量,第二个参数是这个可变参数的类型。
④最后用va_end宏结束可变参数的获取。
可变参数的限制:
①参数列表中至少有一个命名参数,这个参数给后面的可变参数提供一些必要的信息。
②这些宏无法直接的盘算实际存在参数数量。
③这些宏无法判断每个参数的类型。
④如果在va_arg中指定了错误的类型,那么它的结果会无法预测的。
实现一个简单的printf函数:
#include<stdio.h>
#include<stdarg.h>
void IntPrintf(int nums)//将一个10进制数从高到低输出!
{
if (nums > 9)
{
IntPrintf(nums / 10);
}
putchar((nums % 10) + '0');
}
void MyPrintf(const char *src, ...)
{
va_list va;//先声明一个va_list变量va
va_start(va, src);//通过va_start来初始化va
while (*src)
{
if (*src == '%')
{
char c = *++src;
switch (c)
{
case 'd'://当'%'下一个字符为'd'时表示,将要访问一个int类型的可变参数
IntPrintf(va_arg(va, int));//va_arg(va_list声明的变量, 将要访问的可变参数的类型),返回一个整型的变量
break;
case 'c'://当'%'下一个字符为'c'时表示,将要访问一个c类型的可变参数
putchar(va_arg(va, char));//返回一个char类型的变量
break;
case 's'://当'%'下一个字符为's'时表示,将要访问一个s类型的可变参数
puts(va_arg(va, char*));//返回一个char*类型的变量
break;
default://当'%'下一个字符不为'd'、's'、'c'时,把'%'和它下一个字符正常输出!
putchar('%');
putchar(c);
break;
}
}
else
{
putchar(*src);
}
src++;
}
}
int main()
{
MyPrintf("%d he%he %c ha%ha %s", 123, 'A', "hello bit");
system("pause");
return 0;
}