zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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 != '');
        pArg = NULL; //等价于va_end
        return;
    }
    
    int main(int argc, char* argv[])
    {
        int i = 1234;
        int j = 5678;
    
        myprintf("the first test:i=%d
    ", i, j);
        myprintf("the secend test:i=%d;%x;j=%d;
    ", 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);               //结束解析

  • 相关阅读:
    c#实现串口操作 SerialPort
    ASP.NET Core 上传大文件无法接收的问题
    如何将qlv格式的腾讯视频转换为mp4格式
    C#中HttpWebRequest的GetRequestStream执行的效率太低,甚至偶尔死掉
    LGPL 与GPL的区别
    ffmpeg
    HTTP协议/RTSP协议/RTMP协议的区别
    C#写的CRC16检验算法
    VS里属性窗口中的生成操作释义
    iOS:APNS推送主要代码
  • 原文地址:https://www.cnblogs.com/liulipeng/p/3443662.html
Copyright © 2011-2022 走看看