c语言中关于可变参数的研究

来源:互联网 发布:淘宝开店上传宝贝技巧 编辑:程序博客网 时间:2024/05/18 04:23
#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将指针清空。

0 0