C语言变参函数

http://www.cnblogs.com/hnrainll/archive/2011/07/06/2099494.html


http://baike.baidu.com/link?url=LVqNiDgwI3huqGZZwD8Pr_iN5TTfUe-zKr6BX380Pm6i5tu3dFGdyT-p2TaV0DzLnRAZ10U5ZbwIYcHS7SKJ-a


http://blog.chinaunix.net/uid-25572546-id-2183161.html


#include <stdio.h>
#include <stdarg.h>
//模拟实现系统提供的printf函数
int 
vpf(char*fmt,...){
va_list ap;
int cnt; 
va_start(ap,fmt);//第一个参数为指向可变参数字符指针的变量,第二个参数是可变参数的第一个参数,通常用于指定可变参数列表中参数的个数
cnt=vprintf(fmt,ap); 
va_end(ap);//将存放可变参数字符串的变量清空
return(cnt);
}
int main(void)
{
int inumber=30;
float fnumber=90.0;
char* string="abc";
vpf("%d\n%f\n%s\n",inumber,fnumber,string);
return 0;
}


http://blog.csdn.net/jiqiren007/article/details/5935125


C语言中有很多变参的使用,例如printf()的原型是int printf(const char *fmt, ...),那么C语言是如何解析和处理这些变参的呢?下面进行简单的总结:

C语言中定义了下面的一些宏,专门用来处理变参:

va_start(va_list ap, char *fmt)

va_arg(va_list ap , Type) //Type是指参数的类型(比如int、char*、double)

va_end(va_list ap)

从上面三个宏可以看到,它们都有一个va_list类型的参数,那么va_list是什么呢?如何定义的呢?

typedef char* va_list;可以看到va_list其实就是char*

下面继续解析上面的三个宏:

  • va_start(va_list ap, char*fmt)

其中ap是va_list类型的,即可变参数列表;而fmt就是printf等类似函数的参数,指明参数的类型等,例如常见的有:%d%s%c%f等等

va_list()操作进行后的效果是:使得ap指向fmt后面的参数列表,即"...".C语言函数参数是从右向左压栈的

这个操作要在其他两个操作前面执行

  • va_arg(va_list ap, Type)

在执行完va_start()操作后,ap就指向了变参的列表,这个时候就可以对变参列表进行操作了,是通过对ap进行操作实现的,因为此时ap指向变参列表

va_arg(va_list ap, Type)的结果是这样的:执行完这个操作后,首先返回ap当前指向的参数;然后ap向后移动,执行下一个参数;因此va_arg()是要循环调用的,直到所有参数都获得

Type是当前参数的类型

  • va_end(va_list ap)

当上面操作进行完后,ap不再使用了,需要调用va_end()操作将ap给清空

根据上面的描述,在C语言中处理变参的过程大概是这样的:

  • 定义va_list 变量,用来指向参数列表
  • 调用va_start()操作,将定义的va_list变量指向变参列表
  • 调用va_arg()操作,获得每个参数
  • 调用va_end()操作,清空va_list变量

从上面的过程可以看到,在执行第三步的时候有点麻烦,比如事先根本不知道参数的类型等,这样调用va_arg()就不太方便了;而在实际中这样的现象是很多的,可以采用下面的策略解决:

当调用完va_start()操作后,ap已经指向了变参列表了;然后调用vprintf(const char *fmt, va_list ap)将参数进行输出。当然也可以调用vsprintf(char *str, const char *fmt, va_list ap)、vsnprintf(char *str, size_t size, const char *fmt, va_list ap)来将变参保存起来进行处理。

 

通过上面的描述,可以实现一个自己的printf了:

int my_printf(cosnt char *fmt, ...)

{

va_list ap; //定义va_list 变量

va_start(ap, fmt); //让ap指向变参...

int n = vprintf(fmt, ap); //调用vprintf进行输出

return n; //返回输出的字符数,printf返回值是int

}

需要注意的地方:

  • 在使用C语言的变参时,需要将变参(即...)放在最后一个参数的位置;并且变参前面至少要有一个普通的参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值