#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將指針清空。