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

来源:互联网 发布:ping命令是哪个端口 编辑:程序博客网 时间:2024/06/08 19:31
#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型的数值才会自动转化

0 0