在我们平常调用函数的时候,会进行传参,调用的函数也会有参数去接收,数量和类型都是对应的。而不定参数函数是指对一个函数传参,参数的个数可以不确定。接下来,我就简单的叙述一下不定参数函数的原理及应用。
在我们刚学C语言的时候,大多会首先接触printf();函数。通过这个函数,我们可以打印变量到屏幕,如:
printf("%d", a);
printf("%d,%d",b,c);
printf();也是一个函数,我们平常也只会应用他,他的功能是想打印多少东西就可以打印多少。但是printf();函数也是有参数的,他的函数内容包含在头文件里面,所以我们只需要使用就可以了。
但是我们现在要考虑的是,在我们设计不定参数函数的时候:
1.如何告诉函数我们传入了几个参数
2.每个参数的类型是什么
3.函数怎样去访问这些参数
4.函数调用完成后如何将参数从堆栈中释放出来
函数定义看似简单,实际上却需要我们解决许多问题。
要解决上面的问题,我们需要了解下面几个宏定义:
va_list 这个是typedef重新定义的一个类型,本质是char *
va_start() 是用来初始化指针的
va_arg() 值指向后面未知参数部分,能拿出我们想要拿出来的值,并且每一次使用,指针都会指向下一个参数
va_end() 是用来释放这个指针的。
调用这几个参数,需要定义 <stdarg.h> 这个头文件。
下面我们来用printf();函数举例说明可变参数函数的调用过程:
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
void print_int(int n)//以字符的形式,递归输出整形
{
if (n > 9)
{
print_int(n / 10);
}
putchar(n % 10 + '0');
}
void print(const char* format,...)
{
va_list arg;//声明arg
va_start(arg, format);//拿第一个参数初始化这个类型。
while (*format != '\0')
{
switch (*format)
{
case 's'://输出字符串类型
{
char * ret = va_arg(arg, char*);//在后面位置参数部分,能拿出想要的值,且使用一次,指针就会指向下一个参数的地址。
while (*ret)
{
putchar(*ret);
ret++;
};
}
break;
case 'd'://输出整形
{
int ret = va_arg(arg, int);
print_int(ret);
}
break;
case 'c'://输出字符型
{
char c = va_arg(arg, char);
putchar(c);
}
break;
default://原样输出
putchar(*format);
break;
}
format++;
}
va_end(arg);
}
int main()
{
print("s d c\n", "abcdef", 10, 'w');
system("pause");
return 0;
}
我们用print函数来模拟实现printf函数,首先print中必要传一个参数,定义为char*。
之后要判断后面到什么类型的数据。其中print函数当中的s,d,c相当于printf();函数中的%s,%d,%c 。
如果出现了s,即后面会出现字符串类型,用putchar输出字符串;
如果出现了d,即后面会出现整形类型,调用print_int函数输出整形;
如果出现了c,即后面会出现字符类型,用putchar输出字符;
如果没有特定的字符,则原样输出。
最后输出的结果为:
需要注意的是:
1.可变参数必须从头到尾逐个访问,可以访问几个之后不再访问,但是不予许直接访问中间的;
2.函数必须至少有一个命名参数,如果一个都没有,就无法初始化。
3.确保每次指的类型都是正确的,否则会出现不可预期的结果。
代码还是写的有点挫,只是希望大家能从这里面学到不定参数函数的使用,如果有什么作物之处,望指正。