va_start() va_end()函数应用

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

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

 1   #include  < iostream >   
 2   void  fun( int  a, 
 3  
 4   int   * temp  =   & a; 
 5   temp ++
 6   for  ( int  i  =   0 ; i  <  a;  ++ i) 
 7  
 8   cout  <<   * temp  <<  endl; 
 9   temp ++
10  
11  
12  
13   int  main() 
14  
15   int  a  =   1
16   int  b  =   2
17   int  c  =   3
18   int  d  =   4
19   fun( 4 , a, b, c, d); 
20   system( " pause " ); 
21   return   0
22  


Output:: 



4

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

1   void  TestFun( char *  pszDest,  int  DestLen,  const   char *  pszFormat, 
2  
3   va_list args; 
4   va_start(args, pszFormat); 
5   _vsnprintf(pszDest, DestLen, pszFormat, args); 
6   va_end(args); 
7   }
8  


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

1).演示如何使用参数个数可变的函数,采用ANSI标准形式

 1   #include 〈stdio.h〉 
 2     #include 〈 string .h〉 
 3     #include 〈stdarg.h〉 
 4      /* 函数原型声明,至少需要一个确定的参数,注意括号内的省略号 */  
 5      int  demo(  char  ); 
 6      void  main(  void  ) 
 7     { 
 8      demo( " DEMO " " This " " is " " a " " demo! " "" ); 
 9     } 
10      /* ANSI标准形式的声明方式,括号内的省略号表示可选参数 */  
11      int  demo(  char  �msg,   ) 
12     { 
13      /* 定义保存函数参数的结构 */
14      va_list argp; 
15       int  argno  =   0 ;  
16       char  para; 
17  
18       /* argp指向传入的第一个可选参数,msg是最后一个确定的参数 */  
19      va_start( argp, msg ); 
20       while  ( 1
21     { 
22      para  =  va_arg( argp,  char ); 
23       if  ( strcmp( para,  "" ==   0  ) 
24      break
25      printf( " Parameter #%d is: %s/n " , argno, para); 
26      argno ++
27      } 
28      va_end( argp ); 
29       /* 将argp置为NULL */
30       return   0
31     } 


2)//示例代码1:可变参数函数的使用

 1   #include  " stdio.h "
 2   #include  " stdarg.h "
 3   void  simple_va_fun( int  start, 
 4  
 5     va_list arg_ptr; 
 6      int  nArgValue  = start;
 7      int  nArgCout = 0 // 可变参数的数目
 8     va_start(arg_ptr,start);  // 以固定参数的地址为起点确定变参的内存起始地址。
 9      do
10     {
11      ++ nArgCout;
12     printf( " the %d th arg: %d/n " ,nArgCout,nArgValue);  // 输出各参数的值
13     nArgValue  =  va_arg(arg_ptr, int );  // 得到下一个可变参数的值
14     }  while (nArgValue  !=   - 1 );  
15      return
16   }
17   int  main( int  argc,  char *  argv[])
18   {
19     simple_va_fun( 100 , - 1 ); 
20     simple_va_fun( 100 , 200 , - 1 ); 
21      return   0 ;
22   }



3)//示例代码2:扩展——自己实现简单的可变参数的函数。
下面是一个简单的printf函数的实现,参考了<The C Programming Language>中的例子

 1   #include  " stdio.h "
 2   #include  " stdlib.h "
 3   void  myprintf( char *  fmt,  // 一个简单的类似于printf的实现, // 参数必须都是int 类型
 4  
 5      char *  pArg = NULL;  // 等价于原来的va_list 
 6      char  c;
 7      
 8     pArg  =  ( char * & fmt;  // 注意不要写成p = fmt !!因为这里要对 // 参数取址,而不是取值
 9     pArg  +=   sizeof (fmt);  // 等价于原来的va_start  
10    
11      do
12     {
13     c  =* fmt;
14      if  (c  !=   ' % ' )
15     {
16     putchar(c);  // 照原样输出字符
17     }
18      else
19     {
20      // 按格式字符输出数据
21      switch ( *++ fmt) 
22     {
23      case ' d ' :
24     printf( " %d " , * (( int * )pArg));  
25      break ;
26      case ' x ' :
27     printf( " %#x " , * (( int * )pArg));
28      break ;
29      default :
30      break ;
31     } 
32     pArg  +=   sizeof ( int );  // 等价于原来的va_arg
33     }
34      ++ fmt;
35     } while  ( * fmt  !=   ' /0 ' ); 
36     pArg  =  NULL;  // 等价于va_end
37      return
38   }
39   int  main( int  argc,  char *  argv[])
40   {
41      int  i  =   1234 ;
42      int  j  =   5678 ;
43      
44     myprintf( " the first test:i=%d/n " ,i,j); 
45     myprintf( " the secend test:i=%d; %x;j=%d;/n " ,i, 0xabcd ,j); 
46     system( " pause " );
47      return   0 ;
48   }

另外,vfprintf是向文件中按照fmt的格式写入,不需要va_arg的参与
va_start(ap, fmt);
vfprintf(cout, fmt, ap);
va_end(ap);


你可能感兴趣的:(va_start() va_end()函数应用)