va_start、va_end、va_list的使用

http://www.cnblogs.com/rainduck/archive/2010/11/10/1873417.html

 1:当无法列出传递函数的所有实参的类型和数目时,可用省略号指定参数表
void foo(...);
void
foo(parm_list,...);

2:函数参数的传递原理
函数参数是以数据结构:栈的形式存取,从右至左入栈.

#include <iostream>



void fun(int a, ...) { int *temp = &a; temp++; for (int i = 0; i < a; ++i) { cout << *temp << endl; temp++; } } int main() { int a = 1; int b = 2; int c = 3; int d = 4; fun(4, a, b, c, d); system("pause"); return 0; } //Output:: //1 //2 //3 //4 

 

3:获取省略号指定的参数
在函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。像这段代码:

TestFun(char* pszDest, int DestLen, const char* pszFormat, ...) { va_list args; va_start(args, pszFormat); _vsnprintf(pszDest, DestLen, pszFormat, args); va_end(args); }

 

4.va_start使argp指向第一个可选参数。va_arg返回参数列表中的当前参数并使argp指向参数列表中的下一个参数。va_end把argp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。

1).

#include <stdio.h> #include <string.h> #include <stdarg.h>



int demo(char*, ...); int main(void) { demo("DEMO", "This", "is", "a", "demo!", ""); } int demo(char* msg, ...) { va_list argp; int argno = 0; char* para; va_start(argp, msg); while (1) { para = va_arg(argp,char*); if (strcmp(para, "") == 0) break; printf("Parameter #%d is: %s\n", argno, para); argno++; } va_end(argp); return 0; }

 

2).

#include <stdio.h> #include <stdarg.h>



void simple_va_fun(int start, ...) { va_list arg_ptr; int nArgValue = start; int nArgCount = 0; va_start(arg_ptr, start); do { ++nArgCount; printf("the %d th arg: %d\n", nArgCount, nArgValue); //输出各参数的值

        nArgValue = va_arg(arg_ptr,int); //得到下一个可变参数的值

    } while (nArgValue != -1); return; } int main(int argc, char * argv[]) { simple_va_fun(100, -1); simple_va_fun(100, 200, -1); return 0; }

3).

#include <stdio.h> #include <stdlib.h>



//一个简单的类似于printf的实现,//参数必须都是int 类型

void myprintf(char* fmt, ...) { char* pArg = NULL;        //等价于原来的va_list

    char c; pArg = (char*) &fmt;    //注意不要写成p = fmt!!因为这里要对参数取址,而不是取值

    pArg += sizeof(fmt);    //等价于原来的va_start

    do { c = *fmt; if (c != '%') { putchar(c); //照原样输出字符

 } else { //按格式字符输出数据

            switch (*++fmt) { case 'd': printf("%d", *((int*) pArg)); break; case 'x': printf("%#x", *((int*) pArg)); break; default: break; } pArg += sizeof(int);//等价于原来的va_arg

 } ++fmt; } while (*fmt != '\0'); pArg = NULL; //等价于va_end

    return; } int main(int argc, char* argv[]) { int i = 1234; int j = 5678; myprintf("the first test:i=%d\n", i, j); myprintf("the secend test:i=%d;%x;j=%d;\n", i, 0xabcd, j); system("pause"); return 0; }

 还记得printf函数调用的时候那个“...”吗?就是可以输入任意的参数。现在你用va_list也可以实现类似的函数声明,printf就是这样做的。
 va_list args;                     //声明变量
 va_start(args,  before);          //开始解析。args指向before后面的参数
 参数类型 var = va_arg(args,  参数类型);//取下一个参数并返回。args指向下一个参数
 va_end(args);               //结束解析

你可能感兴趣的:(start)