浅析printf中的变参传递
这篇文章主要探讨一种printf的实现,这个是一个实时地记录,错误在所难免,还请谅解。
原型
首先我们来看看printf的实现原型:
typedef struct
{
int32_t dest; // 定义输出终端
void (*func)(char); // 定义输出函数
char *loc;
} PRINTK_INFO;
int printf (const char *fmt, ...)
{
va_list ap; // 变参宏定义, char *ap
int32_t rvalue; // 返回值
PRINTK_INFO info;
/* 初始化info变量 */
info.dest = DEST_CONSOLE;
info.func = &out_char;
/*
* Initialize the pointer to the variable length argument list.
*/
va_start(ap, fmt); //(void)(ap = (char *)&fmt)
rvalue = printk(&info, fmt, ap);
/*
* Cleanup the variable length argument list.
*/
va_end(ap);
return rvalue;
}
我们来看看va_list, va_start, va_end, va_arg的定义:
#ifndef _MSL_VA_LIST_TYPE
#define _MSL_VA_LIST_TYPE char *
#endif
#ifndef _MSL_VA_LIST_DEFINED
typedef _MSL_VA_LIST_TYPE va_list;
#define _MSL_VA_LIST_DEFINED
#endif
#define __va_start(parm) (__std(va_list))(&parm) /*- mm 981014 -*/
#define va_start(ap, parm) (void)(ap = (va_list)&parm) /*- US 011402 -*/
#define va_arg(ap, type) \
(__builtin_vargtype(type) == 1 \
? /* Float or Long Aligned Types */\
(*(type *) (((((unsigned int)((ap)))>>1)&1) == 1 ? ((ap)-=(sizeof(type) +2)) : ((ap)-=sizeof(type)))) \
: /* Everything else */\
(*(type *) ((ap) -=((sizeof(type) <= 2) ? 2:sizeof(type))))\
)
#define va_end(ap) ((void) 0)
这里看起来va_list
就是一个指针而已。再来看看printk
里面是怎么读取这个参数的:
int32_t ival;
int32_t vlen;
char vstr[33];
char *vstrp;
ival = (int32_t)va_arg(ap, int32_t);
vlen = printk_mknumstr(vstr,&ival,TRUE,10);
vstrp = &vstr[vlen];
我们来展开va_arg
这个宏:
(int32_t)va_arg(ap, int32_t);
/* type convert */
(long)va_arg(ap, long);
/* micro convert */
(long) (*long *)(((((unsigned int)((ap))) >> 1)&1) == 1 ? ((ap)-=(sizeof(long) + 2)) : ((ap)-=sizeof(long))))
这里实际就是按照类型的大小直接移动相应的大小,然后进行强制类型转换,当然这个都是要和编译器相对应的,因为参数具体怎么传递还是和编译器相关的。
最后更新于 2019-03-15 05:53:53 并被添加「」标签,已有 2123 位童鞋阅读过。
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。