C和指针 第七章 可变参数

可变参数列表是通过stdarg.h内的宏来实现的:

类型 va_list

三个宏:

  va_start

  va_arg

  va_end

我们可以声明一个va_list变量,与这三个宏配合使用。

可变参数必须要有一个命名参数,因为可变参数是通过栈来实现的,函数中的最右边的参数最先入栈。

void function(int a, int b, int c)
{
    int d;    
    ...
}

其栈结构为

    0x1ffc-->d

    0x2000-->a

    0x2004-->b

    0x2008-->c

栈的空间是连续的,所以函数第一个必须是命名参数,这样就可以通过第一个参数来寻址,根据类型所占字节偏移,获取后续的所有可变参数值。

下面是利用可变参数计算平均值函数:

#include <stdarg.h>

float average(int n_num, ...)
{
	int count;
	float sum = 0;

	//var_arg是一个指针,通过va_start指向第一个命名参数位置
	va_list var_arg;
	va_start(var_arg, n_num);

	for (count = 0; count < n_num; count++) {
		//va_arg第二个参数是类型,根据类型来偏移获取参数值
		sum += va_arg(var_arg, int);
	}

	//让指针指向NULL,不在指向堆栈
	va_end(var_arg);

	return sum / n_num;
}

所以这些宏存在两个问题,一来无法确定参数数量,因为不同类型所占空间不同,二来无法确定类型,printf函数的类型是通过字符串中的格式字符串来提取类型实现的。

参考:http://blog.chinaunix.net/uid-20545038-id-1648593.html

     http://www.cnblogs.com/cpoint/p/3368993.html

原文地址:https://www.cnblogs.com/yangxunwu1992/p/5782404.html