SunBo

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

输出结果:

这段代码主要是想说明:函数的参数在传入时,是做类型的转换的,也就是参数在入栈时就已经被截取了(例如long 传入 char 时);其中还包括了强制类型转换的存储结果,和用不符合变量类型的格式输出时,结果的不同。

 

由这段代码想到了printf的实现,想到了printf需要先解析那个const char *str中的格式字符来确定va_list的指针类型,移动大小。下面是一位大侠对printf的解释,很好!!

int     DEFUN(printf,   (format),   CONST   char   *format   DOTS)
{
    va_list   arg;
    int   done;

    va_start(arg,   format);
    done   =   vprintf(format,   arg);
    va_end(arg);

    return   done;
}

可以看到 printf 其实在内部调用的是 vprintf ,通过查看 vprintf.c 中的内容,我们可以看到 vprintf 其实是通过 vfprintf 实现的,它的函数原型是这样的:

int     DEFUN(vfprintf,   (s,   format,   args),
            register   FILE   *s   AND   CONST   char   *format   AND   va_list   args)


这个函数的整体执行结构是这样的:

register   CONST   char   *f;                                 //
可以看到 f 是一个 const   char 的指针
   
    f   =   format;                          
    while   (*f   !=   '/0 ')
{                                                            

  ...
  if   (*f   !=   '% ')
  {
    ...
  }

  if   (*f   ==   '% ')
  {
      fc   =   *f++;
      ...
    switch   (fc)
      {
              case   'd ':
                        ...
              case   'c ':
                        ...
                ....
        }
  }
        }
从上面的结构我们可以看出,函数首先读取字符串中的字符,然后一个个比较,如果是 % ,则马上用 switch...case 结构判断后续字符

在每一个 case 语句块里面,都有这样的语句:

  nextarg(...);
  outchar(...);

  nextarg()
是一个宏,有如下宏定义

#define   castarg(var,   argtype,   casttype)   /
    var   =   (casttype)   va_arg(args,   argtype)

#define   nextarg(var,   type)   castarg(var,   type,   type)

一出现 va_arg ,我们就很熟悉了,这个宏的作用就是读取可变参数,在这里的作用就是将 args 中的内容读入。也就是利用栈顶指针读取
栈中的内容。

outchar(...)
也是一个宏,它的定义如下

#define   outchar(x)                                                                           /
    do                                                                                                                               /
        {                                                                                                                                 /
            register   CONST   int   outc   =   (x);                       /
            if   (putc(outc,   s)   ==   EOF)                                           /
  RETURN(-1);                                                                                         /
            else                                                                                                               /
  ++done;                                                                                                           /
        }   while   (0)

posted on 2009-07-30 17:29  SunBo  阅读(1002)  评论(0编辑  收藏  举报