函数的可变参数详谈
可变参数的英文表示为:variable argument.O~(u WjP9^;~它在函数的定义时,用三个点号'.'表示,用逗号与其它参数分隔.
可变参数的特点:不像固定参数那样一一对应,也不像固定参数有固定的参数类型和参数名称;可变参数中个数不
定可是传入的是一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有
实际的名称与之相对应.
由此可见,可变参数的形式非常自由而富有弹生.因些,它给那些天才程序员有更大地想象和发挥空间.
然而,更多地自由,同样也加大操作上的难度.NzXt2Yy!}/nF
以下就对可变参数的几个方面作一定的介绍./YFaJ;[3{H7e
1)可变参数的存储形式.8I$Z.@#s?y X3Eh
1To"k$u p2^5hQ
大家都知道,一般函数的形参属于局部变量.而局部变量就是存储在内存的栈区(所谓的栈区:由编译器自动分配释放,}ja2L(^
存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。).可变参数也是存储在内存栈区.%}{ v HM tI
在对函数的形参存储的时侯,编译器是从函数的形参的右边到左边逐一地压栈,-o4q}2^0I#N9U#oT$d
这样保证了栈顶是函数的形参的第一个参数(从左到右数).而80x86平台下的内存分配顺序是从高地址内存到低地址内存.C(_H$vr'P
因此,函数的形参在内存的存储形式如下图(以fun(int var1,int var2,...,int var3,int var4)为例):&EwMnc^6i4Q
栈区:
D]$~I:~lR
|栈顶 低地址
$~_(Y c[x%j ]
|第一个固定参数var1
|可变参数前的第一个固定参数var2 q'h p5lAY
|可变参数的第一个参数
|...#l,QQ&h6c%j:p|
|可变参数的最后一个参数
|函数的倒数第二个固定参数var3
|函数的最后一个固定参数var46h O#_ ~&v1XV;b
|...
|函数的返回地址+B&W h8iu"m
|...
|栈底 高地址
2)使用可变参数所用到头文件和相关宏说明
mvaW(P.j]#F
在此,以TC2.0编译器为参考对象来说明.^ Tm"TD0B
可变参数的相关定义在TC2.0的名为"STDARG.H"的头文件中.G0Z9Mi7t8u
此文件为:O3j3v[G'v-{ J
/* stdarg.h
Definitions for ACCESSing parameters in functions that acceptmw ~pT B7A"u0L
a variable number of arguments.
F8aU;nW;b H(JB'^G
Copyright (c) Borland International 1987,1988
All Rights Reserved.
*/
#if __STDC__dH@)n }
#define _Cdecl
#else8M&w~1`{
#define _Cdecl cdecl
#endif\dwNV+z;@*I
6I6y+@y.\`&Y1ju
#if !defined(__STDARG)1U5oM7R7zj+o.r#|PIm5BA
#define __STDARG
typedef void *va_list;1C%kEB/i aB@t*Z
JiA0UXc
#define va_start(ap, parmN) (ap = ...)
#define va_arg(ap, type) (*((type *)(ap))++)
#define va_end(ap)8]*]+DA-}M^,amj
#define _va_ptr (...)
#endif
Rf fBS,@
以上为"STDARG.H"的内容.mo"@0?8[.G
该文件定义了使用可变参数所用到的数据类型:typedef void *va_list;
va_start(ap,parmN)起到初始化,使用得ap指向可变参数的第一个参数.ap的类型为va_list,