可变参数列表的函数调用 va_list va_start va_arg va_end

    当无法列出函数所有形参的类型和数目时,可用省略号指定参数表,例如:

           void foo(...);
           void foo(parm_list,...);

下面介绍这种可变参数列表的函数该如何处理传递来的参数。

 

1. 函数参数的传递原理

    函数参数是以数据结构——栈的形式存取,参数从右至左入栈。eg:

                    void func(int x, float y, char z);
调用函数的时候,实参 char z 先进栈,然后是 float y,最后是 int x,因此在内存中变量的存放次序是 x->y->z。因此,从理论上说,只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,总可以找到其他的输入变量。

 

2. 处理可变参数列表的宏

在<stdarg.h> 里定义了几个重要的处理可变参数列表的宏:

typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ANSI version */
type va_arg ( va_list ap, type );
void va_end ( va_list ap );

 

va_list  是一个字符指针类型,用于定义指向省略号"..." 所代表的参数列表的指针,如定义: 

                               va_list  ap;

va_start 用于初始化上面定义的指针,使其指向"..." 参数列表的起始地址,va_start的第二个

         参数就是邻近"..." 参数列表的参数,用于定位"..." 参数列表;

va_arg   用于获取参数,它的第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回

         这个指定类型的值,并且把 ap 的位置指向变参表的下一个变量位置;

va_end   将参数ap 置为 NULL,关闭指针,以免产生悬指针。

 

3. 示例

void TestFun(char* pszDest, int DestLen, const char* pszFormat, ...)
{
  va_list args;
  va_start(args, pszFormat);    //一定是邻近“...”的那个参数
  _vsnprintf(pszDest, DestLen, pszFormat, args);
  va_end(args);
 }

例中函数_vsnprintf用于输出 "..." 列表参数,其说明如下:

  头文件        

    #include <stdarg.h>

  函数声明:

  int _vsnprintf(char *buffer, size_t max_count, const char *format, va_list vArgList);

  参数说明:

  1). char *buffer [out],把生成的格式化的字符串存放在这里.

  2). size_t max_count [in], buffer可接受的最大字节数,防止产生数组越界.

  3). const char *format [in], 格式化字符串

  4). va_list vArgList [in], va_list变量. va:variable-argument:可变参数

  用法类似于vsprintf,只不过加了max_count的限制.

  返回值说明:

  如果成功调用此函数,返回写到buffer中的字符的个数(不包括结尾的'\0')。snprintf和vsnprintf函数不能够写多于size大小(包括结尾的'0')的字节数。如果输出因为以上原因被截断,返回成功写入buffer的字符数(不包括结尾的'\0'),如果有足够的内存空间的话。所以,如果返回值等于size或者大于size,表示输出到buffer的字符被截断,如果输出过程中遇到错误,则返回一个负数。


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通过va_listva_start、va_argva_end宏是C语言中用于处理可变参数的一组宏。它们通常用于函数中,当函数需要接受不定数量的参数时,可以使用这些宏来获取和处理这些参数。 具体介绍如下: 1. va_listva_list是一个类型,用于声明一个指向参数列表的指针。它在函数中用于存储可变参数的信息。 2. va_start:va_start宏用于初始化va_list指针。它接受两个参数,第一个参数是一个va_list类型的变量,第二个参数是可变参数列表中最后一个已知的固定参数的名称。通过调用va_start宏,可以将va_list指针指向可变参数列表中的第一个可变参数。 3. va_argva_arg宏用于获取可变参数列表中的下一个参数的值。它接受两个参数,第一个参数是va_list类型的变量,第二个参数是要获取的参数的类型。通过调用va_arg宏,可以依次获取可变参数列表中的每个参数的值,并且每次调用后,va_list指针会自动指向下一个参数。 4. va_endva_end宏用于结束对可变参数列表的访问。它接受一个参数,即va_list类型的变量。通过调用va_end宏,可以释放与可变参数列表相关的资源。 使用这些宏的一般步骤如下: 1. 在函数中声明一个va_list类型的变量。 2. 调用va_start宏,将va_list指针指向可变参数列表中的第一个可变参数。 3. 使用va_arg宏依次获取可变参数列表中的每个参数的值。 4. 调用va_end宏,结束对可变参数列表的访问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值