strarg.h可以实现变参。
在这个头文件中有四个宏用来处理变参。
va_list 是一个指针,用来指向参数第一个参数的首地址
va_start是用来初始化这个指针的,参数为va_list和有可变参量的个数。
va_arg用来取出va_list中的值,参数为va_list和参数类型。
va_end用来清理这个过程中处理的值。
完成变参函数需要以下几个步骤:
1.在函数原型中使用省略号。注意省略号要为最后一个参数,省略号之前可以有任意数量的参数。
2.在函数定义中创建一个va_list类型的变量,用来装变参的地址。
3.用va_start完成初始化
4.用va_arg访问整个参数列表。
5.用va_end完成清理工作。防止内存泄漏。
在源码中:
strarg.h中包含了vadefs.h头文件,并且定义了宏va_start,va_arg和va_end,原型为_crt_va_start,_crt_va_arg,_crt_va_end。
在vadefs头文件中:
va_list定义为char*型。
_crt_va_start(ap,v) 为( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v))
_crt_va_arg(ap,t) 为( * (t *)(((ap += _INTSIZEOF(v)) - _INTSIZEOF(v)) )
_crt_va_end(ap) 为( ap = (va_list)0)
其中:
_ADDRESSOF(v) 为 ( &reinterpret_cast<const char &> (v) )
_INTSIZEOF(v) 为 ((sizeof(n) + sizeof(int) -1 ) &~(sizeof(int) -1)
计算的时候_crt_va_start 先给ap初始化,通过v的地址得到变参的第一个首地址,之后用_crt_va_arg来在其中取出每个元素的值,最后用_crt_va_end给ap赋空。
只要ap赋空就不能再使用了,因为分配的内存在栈上,当程序退出函数的时候会自动回收,不用担心内存泄漏。
宏 _INTSIZEOF(v) 传入值为int char 和short 的时候 计算结果为 4 传入值为double 是结果为8 也就意味着,在栈中,小于int类型的数据会被按照四个字节存储,栈中每一个变量都是最少占四个字节。