先来个例子,后面再说明
#include <stdio.h> #include <stdarg.h> int myprintf(char * format, ...) { va_list ap; int int_value = 0; char char_value = ' '; char *str_value = NULL; va_start(ap,format); int_value = va_arg(ap, int); char_value = va_arg(ap, char); str_value = va_arg(ap, char *); printf("%d %c %s %s /n",int_value, char_value , str_value, format); va_end(ap); return 0; } int main() { myprintf("format string ",555,'c', "43234"); return 0; }
上面的程序我在vc6.0编译通过
现在说一下可变参数的用法
第一步:函数声明 functionname(char * format, ...)
第二步:定义va_list 变量 ap;
第三步:使ap和参数列表关联起来va_start(ap,format);
第四步:你可以按照参数列表即format字符串接收你的参数。
使用va_arg(ap, 参数类型);
va_arg宏会按照参数类型从ap中依次取得一个你传入的变量值,
在例子中,我没有按照format进行格式读取,我想这个不影响你对变参数的理解。
程序的最后使用va_end(ap);释放掉ap;
原理:(一种可能的实现方法)
假设参数压栈为从前往后从下往上;
即test(a,b,c,d);
会先压a入栈最后压d;
而栈低指针小于栈顶指针;
于是
typedef char * va_list;
#define va_start(ap,v) ( ap = (va_list)&v + sizeof(char*))
#define va_arg(ap,t) ((t *)(ap += sizeof(t))[-1]
#define va_end(ap) ( ap = (va_list)0 )
另外:
1、设置缓存setbuf(stdout, buf);
2、INT_MAX等宏在 limits.h中定义
3、文件A.c中定义了char str[] ="test";在其他文件中使用,则如下声明 --> extern char str[];或c++中的const char *str;
4、 errno 保存着错误编号
以上仅是理论,实际中很少直接写变参函数,都是变相调用系统函数实现。实现模板如下
int writeFormat(char* format, ...) { va_list ap; char string[1024]; va_start(ap,format); int size = vsprintf(string,format,ap); va_end(ap); // 这里对格式化后的字符串进行处理 return 0; }