现在的位置: 首页 > 综合 > 正文

va_start() va_end()函数应用

2013年09月10日 ⁄ 综合 ⁄ 共 3178字 ⁄ 字号 评论关闭

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);


抱歉!评论已关闭.