`
xitongyunwei
  • 浏览: 925896 次
文章分类
社区版块
存档分类
最新评论

可变参数函数的实现

 
阅读更多

前提要求:包含#include <stdarg.h>,该头文件中定义了一个va_list类型和三个宏——va_start、va_list和va_end。

标准 C 库 <stdarg.h>

它接受一个格式字符串,并且后面跟随任意指定的参数,根据实际需要而确定入参的个数。

实际上它的实现要依赖于一个标准 C 库 <stdarg.h>,standard argument(标准参数) 的意思。下面先稍为介绍一下 <stdarg.h>,或者在 C++ 中的 <cstdarg> 的功效:

这实际上是一组初始化和调用可变参数的宏,下面先介绍一下可变参数表的调用形式以及原理:

首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址,举个例子如下:

void func(int x, float y, char z);

那么,调用函数的时候,实参char z 先进栈,然后是 float y,最后是 int x,因此在内存中变量的存放次序是 x->y->z,因此,从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,则总可以顺藤摸瓜找到其他的输入变量。

然后是可变入参表格式,省略的参数用 ... 代替,但必须注意:

1. 只能有一个 ... 并且它必须是最后一个参数;

2. 不要只用一个 ... 作为所有的参数,因为从后面可以知道,这样你无法确定入参表的地址。

举个例子,声明函数如下:

void func(int x, int y, ...);

然后调用:func(3, 5, 'c', 2.1f, 6);

于是在调用参数的时候,编译器则不会检查实际输入的是什么参数,只管把所有参数按照上面描述的方法,变成实参堆放在内存中,在本例中,内存中依次存放 x=3, y=5, 'c', 2.1f, 6

但是有一个需要注意的地方,这些东西只是紧挨着堆放在内存中,于是想要正确调用这些参数,必须知道他们确切的类型,并且我们也关心这个参数表实际的长度,然而不幸的是,这些我们无从得知。因此,这个解决办法决不是高明的,从某种程度上说,这甚至是一个严重的漏洞。因此,C++ 很不提倡去使用它。不过缺点归缺点,万不得已的时候我们还是得用,但是我们对里面输入变量的时候,应该对入参的类型有一个清醒的认识,否则这样的操作是很危险的。

下面是 <stdarg.h> 对上面这一个思路的实现,里面重要的几个宏定义如下:

typedef char* va_list;

void va_start ( va_list ap, prev_param ); /* ANSI version */

type va_arg ( va_list ap, type );

voidva_end( va_list ap );

其中,va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。


【实现过程实例】

/*
 * 作者:夏侯佐鑫
 * 日期: 2012.06.21
 * 功能:可变参数计算平均值 
 */
#include <stdio.h>
#include <stdarg.h>

float average(int n_values, ...)
{
	va_list var_arg;
	int count = 0;
	float sum = 0;
	
	/*
 	 * 可变参数访问 
	 */
	 va_start(var_arg, n_values);  //function:将var_arg变量设置为指向可变参数部分的第一个参数 
	/*
 	 * 添加取自可变参数列表值 
	 */	  
	 for(count=0; count<n_values; count+=1)
	 {
	 	sum += va_arg(var_arg, int);
	 }
	 
	 va_end(var_arg);
	 
	 return sum / n_values;
}

int main(void)
{
	float a = average(3, 20,10,30);  //第一个值为后续参数个数 
	
	printf("求平均值结果为%f\n", a);
	
	return

【结果】

分享到:
评论

相关推荐

    C语言中可变参数函数实现原理

    C语言中可变参数函数实现原理 printf()\scanf() 可变参数函数的设计

    揭密X86架构C可变参数函数实现原理_海枫的专栏-CSDN博客1

    如果读者对C语言可变参数函了解不多,可参考拙文「亲密接触C可变参数函数」,本文不再讲述C语言可变参数函数本身的定义,以及va_start、va_arg和va_e

    使用可变参数实现printf()函数

    通过可变参数函数实现printf()函数功能,可将其应用于单片机,ARM裸机等的串口输出中去,并且新增了[%b:实现二进制输出,原来printf函数不能实现的功能]。也可将其使用的液晶的字符类驱动中去。

    delphi实现类C可变参数函数

    delphi实现类C可变参数函数

    Matlab中使用varargin来实现参数可变的函数

    在写《用Matlab演示Parzen窗法》的时候,我还不知道怎样在m中设计可变参数函数。 后来阅读一些m自带函数源码时发现了它的秘密,只要将最后一个参数设置为

    从printf谈可变参数函数的实现

    一直以来都觉得printf似乎是c语言库中功能最强大的函数之一,不仅因为它能格式化输出,更在于它的参数个数没有限制,要几个就给几个,来者不拒。printf这种对参数个数和参数类型的强大适应性,让人产生了对它进行...

    参数数目可变的函数 求和

    输入的第一个数字为准备输入函数的个数。 对后面输入的函数求和。

    C语言可变参数及printf函数的实现

    C语言 可变参数及printf函数的实现

    C51可变参数讲解.pdf

    keil C51可变参数讲解,自定义允许访问可变长度参数列表的函数。

    C可变参数函数实现

    一直以来习惯了使用printf函数,但是对于可变参数没有深入研究过,觉得可变参数是一个神奇的技术。想研究研究看可变参数的使用和原理。目前C提供的可变参数的申明为 void function(const char *format, …);  ...

    用可变参数的原理实现简单的printf函数

    利用可变参数实现简单的printf函数 编写了两种实现方法, 1,用stdarg.h自带的va_start,va_arg等函数实现 2,根据可变参数的原理实现 主要是用于加深对可变参数的理解 vc6.0 测试通过

    C语言可变参数函数范例-程序源码

    示范如何在C语言实现可变参数函数 比如:printf(char *format,...) 有两个示范例程: //把多个字符串连接起来 char *StrCat(char *src,...) //把多个参数加总 int SumAll(int number1,...) 注意事项请看My相关...

    用C语言实现参数个数可变的函数

    本文介绍一种用C语言实现参数个数可变的函数,感兴趣的朋友可以看看。

    C/C++可变参数函数的实现

    主要介绍了C/C++可变参数函数的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    C++可变参数的实现方法

    可变参数的实现要解决三个问题: 1.如何调用带有可变参数的函数...printf和scanf是C语言标准库中最常见的可变参数函数, printf的签名是 代码如下:int printf(const char* format, …); 其中,… 表示可变参数,现在模仿

    C++可变参数函数的实现方法示例

    C++编程中实现可变参数函数有多种途径,本文介绍一种最常见的实现途径,即可变参数宏方法:形参生命为省略符,函数实现时用参数列表宏访问参数。 1. 可变参数宏实现变参函数 可变参数宏实现可分为以下几个步骤: ...

    c语言基于stdarg.h的可变参数函数的用法

    C语言编程中有时会遇到一些参数个数可变的函数,本文详细讲解了可变参数函数的实现原理,分享给大家 在开始学习C语言的函数的时候,我们就知道函数的参数个数应该是在函数声明的时候就指定的,这一点我们没有任何疑问...

    C语言可变参数函数详解示例

    先看代码 代码如下:printf(“hello,world!”);其参数个数为1个。printf(“a=%d,b=%s,c=%c”,a,b,c);其参数个数为4个。...如何实现可变参数函数?2. 编写可变函数准备为了编写可变参数函数,我们通常需要用到头文

    C语言难点分析整理

    7. C中可变参数函数实现 38 8. C程序内存中组成部分 41 9. C编程拾粹 42 10. C语言中实现数组的动态增长 44 11. C语言中的位运算 46 12. 浮点数的存储格式: 50 13. 位域 58 14. C语言函数二维数组传递方法 ...

Global site tag (gtag.js) - Google Analytics