#include <stdio.h>
#include <stdarg.h>
void PrintLines(char *first,...)
{
char *str;
va_list v1;
str = first;
va_start(v1,first);
do
{
printf("%s\n",str);
str = va_arg( v1 , char* );
} while (str != NULL );
va_end(v1);
}
int main(int argc, char* argv[])
{
PrintLines("First","Second","Third","Fourth",NULL);
return 0;
}
函数如何定义可变参数
//eg:
void PrintLines(char *first,...);
//用三个点来代表可变参数
函数如何接受处理可变参数
使用 va_list va_start va_end va_arg
那他们究竟是什么呢
typedef char * va_list;
#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end
继续(我的测试平台:win32,x86,c文件)
#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 )
#ifdef __cplusplus
#define _ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )
#else
#define _ADDRESSOF(v) ( &(v) )
#endif
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
所以 va_list 本质上是 char *,v1存储的的是参数first的内存地址
v1 = (char *)_ADDRESSOF(first) + _INTSIZEOF(first)
而 va_arg 则可以不断根据类型向后遍历变量,因为参数栈本身是不会标明参数个数的,所以我们要在调用函数的时候,表明确定参数个数的方法,比如printf中的fmt,或者在函数的第一个参数处指明参数个数,或者最后一个变量设置为NULL等等。
最后使用va_end将指针清空。