windows学习笔记2——va_list,va_start,va_end,va_arg的使用

时间:2021-04-09 03:40:29

有时我们需要编写这样的函数:函数的参数个数不确定,就像printf(const char* szFormat, ...);一样。这时候,如何方便地处理这些变参是一件需要仔细考虑的问题,例如我们需要在函数中判断用户输入的参数中是否有等于0的实参,你该怎么做?

幸运的时,大师级的先驱们已经为我们做好了,下面让我们一起来研究一下va_arg, va_endva_start等相关的用法吧!<参看MSDN>

 

   1、需要的头文件和库文件

   ANSI 版(windows下):

      <stdio.h><stdarg.h>

   UINX 

      <varargs.h>

   库文件:

      单线程静态库:LIBC.LIB

      多线程静态库:LIBCMT.LIB

      MSVCRT.DLL的导入库:MSVCRT.LIB

   2、鉴于学习的window,暂时不考虑UINX

      在stdarg.h中:关于va_list的定义如下:

              windows学习笔记2——va_list,va_start,va_end,va_arg的使用

       关于va_start, va_end, va_arg的定义如下:

               windows学习笔记2——va_list,va_start,va_end,va_arg的使用

 

 3MSDN中关于va_start,va_end,va_arg的描述

type va_arg(va_list arg_ptr,  type);

    void va_end(va_list arg_ptr);

    void va_start(va_list arg_ptr, prev_param);(ANSI)

    type 为接收的参数的类型

    arg_ptr 为指向参数列表的指针

    prev_param 为 原始参数列中最前面的(第一个)参数。

    va_start:设置参数列表指针arg_ptr指向传递给函数参数表的第一个原始参数(prev_param

  va_end宏:在所有参数被检索完成后,va_end重置指针arg_ptr指向NULL

  va_arg宏:接收arg_ptr指向的type类型的变量,同时使arg_ptr加一,指向参数列表的下一个变量,它是通过宏中的第二个参数type来确定下一个变量的开始位置,va_arg可以在函数中使用任意多次来接收参数列表中的参数。

4、用例:

     #include <stdio.h>

     #define ANSI

     #ifdef ANSI

     #include <stdarg.h>

      //声明一个变参函数

      int average(int first, ...);

     #endif

     int average(int first, ...)

     {

         int count =0, sum =0, i= first;

         va_list m_args;//定义自己的参数列表指针

         va_start(m_args, first);//使参数列表指针指向输入参数表的第一个//参数

         while(i != -1)

        {

            sum+=i;

            count++;

            i = va_arg(m_args, int);//取出当前参数

        }

        va_end(m_args);//置空列表指针,以便下一次使用

        return( sum?(sum/count):0);

     }

     int main(int crgc, char** argv)

     {

         printf("%d", average(1, 2, -1));

         printf("%d", average(1, 2, 3, -1));

         printf("%d", average(1, 2, 3, 4, -1));

     }