Welcome

首页 / 软件开发 / C语言 / 从printf谈可变参数函数的实现

从printf谈可变参数函数的实现2010-10-07 vckbase 戎亚新一直以来都觉得printf似乎是c语言库中功能最强大的函数之一,不仅因为它能格式化输出,更在于它的参数个数没有限制,要几个就给几个,来者不拒。printf这种对参数个数和参数类型的强大适应性,让人产生了对它进行探索的浓厚兴趣。

1.使用情形

int a =10;
double b = 20.0;
char *str = "Hello world";
printf("begin print ");
printf("a=%d, b=%.3f, str=%s ", a, b, str);
...

从printf的使用情况来看,我们不难发现一个规律,就是无论其可变的参数有多少个,printf的第一个参数总是一个字符串。而正是这第一个参数,使得它可以确认后面还有有多少个参数尾随。而尾随的每个参数占用的栈空间大小又是通过第一个格式字符串确定的。然而printf到底是怎样取第一个参数后面的参数值的呢,请看如下代码

2.printf 函数的实现

//acenv.h
typedef char *va_list;
#define _AUPBND (sizeof (acpi_native_int) - 1)
#define _ADNBND (sizeof (acpi_native_int) - 1)

#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
//start.c
static char sprint_buf[1024];
int printf(char *fmt, ...)
{
va_list args;
int n;
va_start(args, fmt);
n = vsprintf(sprint_buf, fmt, args);
va_end(args);
write(stdout, sprint_buf, n);
return n;
}
//unistd.h
static inline long write(int fd, const char *buf, off_t count)
{
return sys_write(fd, buf, count);
}