您现在的位置: > 首页 > 程序开发 > C语言教程
>> 最新教程
>> 热门教程
>> 最新游戏资讯
>> 热门游戏资讯
从printf谈可变参数函数的实现
作者:本站                来自:安迪教程网                 加入时间:08-08-13                进入论坛讨论

  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);
}
3. 分析

  从上面的代码来看,printf似乎并不复杂,它通过一个宏va_start把所有的可变参数放到了由args指向的一块内存中,然后再调用vsprintf. 真正的参数个数以及格式的确定是在vsprintf搞定的了。由于vsprintf的代码比较复杂,也不是我们这里要讨论的重点,所以下面就不再列出了。我们这里要讨论的重点是va_start(ap, A)宏的实现,它对定位从参数A后面的参数有重大的制导意义。现在把 #define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) 的含义解释一下如下:

<<< << < 1 2 3 > >> >>>
联系方式:QQ:6084884 email:agwcn@126.com 粤ICP备05055782号
本网站中发布的文章只代表发表人的个人观点,不代表安迪教程网网站的立场
copyright© 2000-2004 安迪教程网 All rights reserved agwcn.com