• 【转载】va_list 可变参数 简介 va_copy vprintf


    【说明】本文转载自 smart 的文章 http://blog.sina.com.cn/s/blog_590be5290100qhxr.html  及百度百科

    va_list是一个宏,由va_start和va_end界定。

          typedef char* va_list;
      void va_start ( va_list ap, prev_param );
      type va_arg ( va_list ap, type );
      void va_end ( va_list ap );
        其中,va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。


        <Step 1> 在调用参数表之前,应该定义一个 va_list 类型的变量,以供后用(假设这个 va_list 类型变量被定义为ap);
        <Step 2> 然后对 ap 进行初始化,让它指向可变参数表里面的第一个参数。这是通过 va_start 来实现的,其第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量;
        <Step 3> 然后是获取参数,调用 va_arg。它的第一个参数是 ap,第二个参数是要获取的参数的指定类型,并返回这个指定类型的值,同时把 ap 的位置指向变参表的下一个变量位置;
        <Step 4> 获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end。它是将输入的参数 ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。

    例子:

    int max(int n, ...)  // 定参 n 表示后面变参数量,定界用,输入时切勿搞错
    {                  
     va_list ap;       // 定义一个 va_list 指针来访问参数表
     va_start(ap, n);     // 初始化 ap,让它指向第一个变参
     int maximum = -0x7FFFFFFF;   // 这是一个最小的整数
     int temp;
     for(int i = 0; i < n; i++)
     {
      temp = va_arg(ap, int);   // 获取一个 int 型参数,并且 ap 指向下一个参数
      if (maximum < temp)
       maximum = temp;
     }
     va_end(ap);       // 善后工作,关闭 ap
     return maximum;
    }

    // 在主函数中测试 max 函数的行为(C++ 格式)
    int main()
    {
     cout << max(3, 10, 20, 30) << endl;
     cout << max(6, 20, 40, 10, 50, 30, 40) << endl;
    }

    百度百科:

     
    收藏
     
    79

    va_list编辑

    本词条缺少信息栏名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!
    VA_LIST 是在C语言中解决变参问题的一组宏,所在头文件:#include <stdarg.h>

    目录

    1概述

    2成员

    ▪ 变量
    ▪ 

    3用法

    4注意问题

     
     

    1概述编辑

    VA_LIST 是在C语言中解决变参问题的一组宏,所在头文件:#include <stdarg.h>

    2成员编辑

    变量

    #ifdef _M_ALPHA
    typedef struct {
    char *a0; /* pointer to first homed integer argument */
    int offset; /* byte offset of next parameter */
    } va_list;
    #else
    typedef char * va_list;
    #endif
    _M_ALPHA是指DEC ALPHA(Alpha AXP)架构。所以一般情况下va_list所定义变量为字符[1] 指针。

    INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:
    #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数):
    #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
    VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):
    #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
    VA_END宏,清空va_list可变参数列表:
    #define va_end(ap) ( ap = (va_list)0 )

    3用法编辑

    (1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
    (2)然后用VA_START宏初始化刚定义的VA_LIST变量;
    (3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
    (4)最后用VA_END宏结束可变参数的获取。

    4注意问题编辑

    (1)可变参数的类型和个数完全由程序代码控制,它并不能智能地识别不同参数的个数和类型;
    (2)如果我们不需要一一详解每个参数,只需要将可变列表拷贝至某个缓冲,可用vsprintf函数;
    (3)因为编译器对可变参数的函数的原型检查不够严格,对编程查错不利.不利于我们写出高质量的代码;
     
     

    va_copy

    void va_copy (va_list dest, va_list src);
    Copy variable argument list
    Initializes dest as a copy of src (in its current state).

    The next argument to be extracted from dest is the same as the one that would be extracted from src.

    A function that invokes va_copy, shall also invoke va_end on dest before it returns.

    Parameters

    dest
    Uninitialized object of type va_list.
    After the call, it carries the information needed to retrieve the same additional arguments as src.
    If src has already been passed as first argument to a previous call to va_start or va_copy, it shall be passed tova_end before calling this function.
    src
    Object of type va_list that already carries information to retrieve additional arguments with va_arg (i.e., it has already been passed as first argument to va_start or va_copy ans has not yet been released with va_end).

    Return Value

    none

    Example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    /* va_copy example */
    #include <stdio.h>      /* printf, vprintf*/
    #include <stdlib.h>     /* malloc */
    #include <string.h>     /* strlen, strcat */
    #include <stdarg.h>     /* va_list, va_start, va_copy, va_arg, va_end */
    
    /* print ints until a zero is found: */
    void PrintInts (int first,...)
    {
      char * buffer;
      const char * format = "[%d] ";
      int count = 0;
      int val = first;
      va_list vl,vl_count;
      va_start(vl,first);
      
      /* count number of arguments: */
      va_copy(vl_count,vl);
      while (val != 0) {
        val=va_arg(vl_count,int);
        ++count;
      }
      va_end(vl_count);
      
      /* allocate storage for format string: */
      buffer = (char*) malloc (strlen(format)*count+1);
      buffer[0]='';
      
      /* generate format string: */
      for (;count>0;--count) {
        strcat (buffer,format);
      }
      
      /* print integers: */
      printf (format,first);
      vprintf (buffer,vl);
      
      va_end(vl);
    }
    
    int main ()
    {
      PrintInts (10,20,30,40,50,0);
      return 0;
    }

    vprintf编辑

    本词条缺少概述名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!
    中文名
    vprintf
    外文名
    vprintf
    类似标准
    库函数vprintf函数与printf函数
    功 能
    送格式化输出到stdout中
    用 法
    int vprint
    printf的功能就是用它来实现的,所不同的是,它用一个参数取代了变长参数表,且此参数是通过调用va_start宏进行初始化。同样,vfprintf和vsprintf函数分别与fprintf和sprintf函数类似。
    函数名: vprintf
    用 法: int vprintf(char *format, va_list param);
    程序例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>
    #include <stdarg.h>
    //模拟实现系统提供的printf函数
    int vpf(char*fmt,...)
    {
    va_list argptr;
    int cnt;
    va_start(argptr,fmt);//第一个参数为指向可变参数字符指针的变量,第二个参数是可变参数的第一个参数,通常用于指定可变参数列表中参数的个数
    cnt=vprintf(fmt,argptr);
    va_end(argptr);//将存放可变参数字符串的变量清空
    return(cnt);
    }
    int main(void)
    {
    int inumber=30;
    float fnumber=90.0;
    char* string="abc";
    vpf("%d%f%s ",inumber,fnumber,string);
    return0;
    }
  • 相关阅读:
    DirectUI精髓之一 控件布局的自动缩放(弹簧特性)
    windows mobile6.5截屏工具
    实现的ATL(AtlSimpleArray)数组任意插入辅助函数
    动态库中单例一记
    ASP.NET组件设计Step by Step(4)
    Asp.net 中服务端控件事件是如何触发的
    PagesSection.EnableEventValidation 属性
    ASP.NET事件回传机制
    (服务器控件)页面框架处理回发数据的过程
    ASP.NET底层架构
  • 原文地址:https://www.cnblogs.com/vanishfan/p/4325218.html
Copyright © 2020-2023  润新知