最近看C可变参数,想到自己写一个简单的printf函数,利用fprintf输出到屏幕上。
#include <stdio.h>
#include <stdarg.h>
int print(char const * fmt, ...)
{
va_list vp;
va_start(vp, fmt);
while(*fmt != '\0')
{
if(*fmt != '%')
fprintf(stdout, "%c", *fmt);
else{
switch(*++fmt)
{
case 'd':
fprintf(stdout, "%d", (int)va_arg(vp, int));
break;
case 'f':
fprintf(stdout, "%f", (double)va_arg(vp, double));
break;
case 'c':
fprintf(stdout, "%c", (int)va_arg(vp, int));
break;
case 's':
fprintf(stdout, "%s", (char *)va_arg(vp, char*));
break;
default:
fprintf(stderr, "error!");
}
}
++fmt;
}
va_end(vp);
}
int main()
{
int i = 10;
float f = 10.123;
char *str = "hello world!";
char ch = 'a';
print("%d %s %c %f\n", i, str, ch, f);
return 0;
}
需要说明的是:
1)从参数列表中读取一个float类型的参数时,要是使用:
(double)va_arg(vp, double)
使用(float)va_arg(vp, float)时出错。
2)读取一个字符型参数时,要使用:
(int)va_arg(vp, int);
因为涉及到存储时的对齐,使用(char)va_arg(vp, char)时,会使参数列表错乱。
3)当使用(char *)va_arg(vp, char*)时,读取的是一个完整的字符串,也就是读到一个字符串结束符为止。
4)关于使用到的几个宏,va_list, va_start, va_arg, va_end等的具体细节及编译时的工作原理,
我参考了:http://pcedu.pconline.com.cn/empolder/gj/c/0507/669879_all.html 。