前提要求:包含#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语言中可变参数函数实现原理 printf()\scanf() 可变参数函数的设计
如果读者对C语言可变参数函了解不多,可参考拙文「亲密接触C可变参数函数」,本文不再讲述C语言可变参数函数本身的定义,以及va_start、va_arg和va_e
通过可变参数函数实现printf()函数功能,可将其应用于单片机,ARM裸机等的串口输出中去,并且新增了[%b:实现二进制输出,原来printf函数不能实现的功能]。也可将其使用的液晶的字符类驱动中去。
delphi实现类C可变参数函数
在写《用Matlab演示Parzen窗法》的时候,我还不知道怎样在m中设计可变参数函数。 后来阅读一些m自带函数源码时发现了它的秘密,只要将最后一个参数设置为
一直以来都觉得printf似乎是c语言库中功能最强大的函数之一,不仅因为它能格式化输出,更在于它的参数个数没有限制,要几个就给几个,来者不拒。printf这种对参数个数和参数类型的强大适应性,让人产生了对它进行...
输入的第一个数字为准备输入函数的个数。 对后面输入的函数求和。
C语言 可变参数及printf函数的实现
keil C51可变参数讲解,自定义允许访问可变长度参数列表的函数。
一直以来习惯了使用printf函数,但是对于可变参数没有深入研究过,觉得可变参数是一个神奇的技术。想研究研究看可变参数的使用和原理。目前C提供的可变参数的申明为 void function(const char *format, …); ...
利用可变参数实现简单的printf函数 编写了两种实现方法, 1,用stdarg.h自带的va_start,va_arg等函数实现 2,根据可变参数的原理实现 主要是用于加深对可变参数的理解 vc6.0 测试通过
示范如何在C语言实现可变参数函数 比如:printf(char *format,...) 有两个示范例程: //把多个字符串连接起来 char *StrCat(char *src,...) //把多个参数加总 int SumAll(int number1,...) 注意事项请看My相关...
本文介绍一种用C语言实现参数个数可变的函数,感兴趣的朋友可以看看。
主要介绍了C/C++可变参数函数的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
可变参数的实现要解决三个问题: 1.如何调用带有可变参数的函数...printf和scanf是C语言标准库中最常见的可变参数函数, printf的签名是 代码如下:int printf(const char* format, …); 其中,… 表示可变参数,现在模仿
C++编程中实现可变参数函数有多种途径,本文介绍一种最常见的实现途径,即可变参数宏方法:形参生命为省略符,函数实现时用参数列表宏访问参数。 1. 可变参数宏实现变参函数 可变参数宏实现可分为以下几个步骤: ...
C语言编程中有时会遇到一些参数个数可变的函数,本文详细讲解了可变参数函数的实现原理,分享给大家 在开始学习C语言的函数的时候,我们就知道函数的参数个数应该是在函数声明的时候就指定的,这一点我们没有任何疑问...
先看代码 代码如下:printf(“hello,world!”);其参数个数为1个。printf(“a=%d,b=%s,c=%c”,a,b,c);其参数个数为4个。...如何实现可变参数函数?2. 编写可变函数准备为了编写可变参数函数,我们通常需要用到头文
7. C中可变参数函数实现 38 8. C程序内存中组成部分 41 9. C编程拾粹 42 10. C语言中实现数组的动态增长 44 11. C语言中的位运算 46 12. 浮点数的存储格式: 50 13. 位域 58 14. C语言函数二维数组传递方法 ...