天天看点

C语言中不定参数函数

在我们平常调用函数的时候,会进行传参,调用的函数也会有参数去接收,数量和类型都是对应的。而不定参数函数是指对一个函数传参,参数的个数可以不确定。接下来,我就简单的叙述一下不定参数函数的原理及应用。

在我们刚学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输出字符;

如果没有特定的字符,则原样输出。

最后输出的结果为:

C语言中不定参数函数

需要注意的是:

1.可变参数必须从头到尾逐个访问,可以访问几个之后不再访问,但是不予许直接访问中间的;

2.函数必须至少有一个命名参数,如果一个都没有,就无法初始化。

3.确保每次指的类型都是正确的,否则会出现不可预期的结果。

代码还是写的有点挫,只是希望大家能从这里面学到不定参数函数的使用,如果有什么作物之处,望指正。

继续阅读