stdarg宏用法--------可变参数调用

stdarg宏------可变参数调用,定义于stdarg.h头文件,是标准库的一部分,这个主要在一些内核代码中经常看到,这个头文件声明了类型va_list和三个宏-----va_start,va_arg,va_end。一般声明一个va_list的变量,与这几个宏配合使用,访问参数的值。
var_arg用来访问参数列表的未确定部分,这个变量通过调用va_start来初始化。
va_start函数的第一个参数是va_list变量的名字,第二个参数是省略号前最后一个有名字的参数。初始化过程把var_arg变量设置为指向可变参数部分的第一个参数。
va_arg,这个宏接受两个参数:va_list变量和参数列表中下一个参数类型。va_arg返回这个参数的值,并使var_arg指向下一个可变参数。

在访问完最后一个可变参数之后,需要调用va_end。

函数在堆栈中的分布情况是:地址从高到低,依次是函数参数列表,函数返回地址,函数执行代码
堆栈中哦,各个函数的分布情况是倒序的
参数在堆栈中的分布情况如下:
最后一个参数
倒数第二个参数

第一个参数
函数返回地址
函数代码段

#include<stdarg.h>
#include<stdio.h>
void simple_va_fun(int a,...)
{
	va_list arg_ptr;
	va_start(arg_ptr,a);		    //第一个可选参数地址
	for(int i=0;i<a;i++)
	{
		int k=va_arg(arg_ptr,int);		//VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
		printf("%d\n",k);
	}
	va_end(arg_ptr);			//将指针置为无效
	return;
}
int main()
{
	simple_va_fun(2,20,30);
	printf("\n");
	simple_va_fun(3,20,30,40);
	return 0;
}

运行结果如下:

20
30

20
30
40

再对比下面的这个代码

#include<stdarg.h>
#include<stdio.h>
void simple_va_fun(int b,int a,...)				//区别,多了一个参数
{
	va_list arg_ptr;
	va_start(arg_ptr,a);		    //第一个可选参数地址
	for(int i=0;i<a;i++)
	{
		int k=va_arg(arg_ptr,int);		//VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
		printf("%d\n",k);
	}
	va_end(arg_ptr);			//将指针置为无效
	return;
}
int main()
{
	simple_va_fun(3,2,20,30);       //这里相应的多了一个参数
	printf("\n");
	simple_va_fun(4,3,20,30,40);
	return 0;
}

再看运行结果:

20
30

20
30
40

也就是说va_start的第二个参数只对省略号前最后一个有名字的参数有效,与前面有名字的参数并无关系。

posted @ 2018-05-02 22:12  W_K_L  阅读(48)  评论(0编辑  收藏  举报