使用varargh.h来实现可变参数列表以及varargh.h实现

#include <varargs.h>
void error(va_list)va_dcl
{
	va_list ap;
	char *format;
	va_start(ap);
	format=va_arg(ap,char *);
	fprintf(stderr,"error: ");
	//某些实现方式暂时未知的工作
	va_end(ap);
	fprintf(stderr,"\n");
	exit(1);
	
}
//error函数的最终版本
#include <varargs.h>
#include <stdio.h>
void error(va_alist)va_dcl
{
	va_list ap;
	va_start(ap);
	char *format;
	format=va_arg(ap,char *);
	fprintf(stderr,"error: ");
	vfprintf(stderr,format,ap);
	va_end(ap);
	fprintf(stderr,"\n");
	exit(1);
}
//利用vprintf来实现printf函数的一种可行的方法,注意不要忘记保存vprintf的结果,我们需要把这个结果返回给printf函数的调用者
#include <varargs.h>
printf(va_list)va_dcl
{
	va_list ap;
	char *format;
	int n;
	va_start(ap);
	format=va_arg(ap,char *);
	n=vprintf(format,ap);
	va_end(ap);
	return n;
}
//实现varargs.h的一个典型实现的一组宏
typedef char *va_list;
#define va_dcl int va_alist;
#define va_start(list) list=(char *)&va_alist;//va_list甚至不是一个宏,只是一个int型的参数,而且va_list就只是一个简单的字符指针,但是在底层的c语言实现中要求函数参数在内存中连续存贮,这样我们只需知道当前参数的地址,就能依次访问参数列表中的其他参数,宏va_start把它的参数设置为va_alist的地址(为避免lint程序警告,这里做了类型转化,而宏va_end则什么也没做)
#define va_end(list)
#define va_arg(list,mode) ((mode*)(list+=sizeof(mode)))[-1]
//最复杂的是宏va_arg,它必须返回一个由va_list所指向的恰当类型的数值,同时递增va_list,使它指向参数列表中的下一个参数,(即递增的大小等于与va_arg宏所返回的数值具有相同类型的对象的长度)。应为类型转化的结果不能作为赋值运算的目标,所以只能先赋值再做类型转化,而不能先类型转化再赋值,所以va_arg宏首先使用sizeof来确定需要递增的大小,然后直接把它加到va_list上,这样得到的指针再被转化为要求的类型,应为该指针现在指向的位置过了一个类型单位的大小,所以我们使用了下标-1来存取正确的返回参数
//这里有一个陷阱需要避免,va_arg的的第二个参数不能被指定为char,short或float类型,应为char和short类型的参数会被转化为int类型,而float类型的参数会自动被自动转化为double类型,应为之前的函数参数没有声明,但是当第二个参数作为指针时,指针并不会自动转化,只有short,char和float型的数值才会自动转化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值