printf中变参的实现

printf中变参的实现

#ifdef _M_CEE_PURE
typedef System::ArgIterator va_list;
#else
typedef char *  va_list;
#endif /* _M_CEE_PURE */

我们使用 typedef char* va_list;//va_list是一个指向char的函数指针

#define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )
_ADDRESSOF(v)的作用是取得v变量的地址。

#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
以int所占的字节为标准进行对其操作。
如果int占四字节,则以四字节对齐为标准读取数据。

在stdarg.h中有下面三个宏的定义
#define va_start
_crt_va_start
#define va_arg
_crt_va_arg
#define va_end
_crt_va_end
红色标注的宏是用户直接使用的宏,下面我们来看一下他们各自的实现,即绿色标注的部分。

在vadefs.h中有上述绿色标注部分的实现。

#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap)      ( ap = (va_list)0 )

解析
1.   #define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
(va_list)_ADDRESSOF(v)得到v的地址
INTSIZEOF(v) 字节对齐后v的大小
最后ap指向v的下一个对象的指针,即所以ap 就指向v后面的参数的起始地址。

2. #define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
分为以下几个step解析:
(1) ap += _INTSIZEOF(t) 指向类型为t的下一个参数的地址。
(2) (ap += _INTSIZEOF(t))- _INTSIZEOF(t) 指向当前类型为t的参数的指针
(3)(t*)((ap += _INTSIZEOF(t))- _INTSIZEOF(t))将当前指针转换成t类型的指针
(4)( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )取得当前指针的值。

3.#define _crt_va_end(ap)      ( ap = (va_list)0 )
将va_list置成无效指针。

以上是printf()变参的实现过程







你可能感兴趣的:(printf中变参的实现)