可變參數(shù)的英文表示為:variable argument.
它在函數(shù)的定義時(shí),用三個(gè)點(diǎn)號(hào)'.'表示,用逗號(hào)與其它參數(shù)分隔.
可變參數(shù)的特點(diǎn):不像固定參數(shù)那樣一一對(duì)應(yīng),也不像固定參數(shù)有固定的參數(shù)類型和參數(shù)名稱;可變參數(shù)中個(gè)數(shù)不
定可是傳入的是一個(gè)參數(shù)也可以是多個(gè);可變參數(shù)中的每個(gè)參數(shù)的類型可以不同,也可以相同;可變參數(shù)的每個(gè)參數(shù)并沒有
實(shí)際的名稱與之相對(duì)應(yīng).
由此可見,可變參數(shù)的形式非常自由而富有彈生.因些,它給那些天才程序員有更大地想象和發(fā)揮空間.
然而,更多地自由,同樣也加大操作上的難度.
以下就對(duì)可變參數(shù)的幾個(gè)方面作一定的介紹.
1)可變參數(shù)的存儲(chǔ)形式.
大家都知道,一般函數(shù)的形參屬于局部變量.而局部變量就是存儲(chǔ)在內(nèi)存的棧區(qū)(所謂的棧區(qū):由編譯器自動(dòng)分配釋放,
存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。).可變參數(shù)也是存儲(chǔ)在內(nèi)存棧區(qū).
在對(duì)函數(shù)的形參存儲(chǔ)的時(shí)侯,編譯器是從函數(shù)的形參的右邊到左邊逐一地壓棧,
這樣保證了棧頂是函數(shù)的形參的第一個(gè)參數(shù)(從左到右數(shù)).而80x86平臺(tái)下的內(nèi)存分配順序是從高地址內(nèi)存到低地址內(nèi)存.
因此,函數(shù)的形參在內(nèi)存的存儲(chǔ)形式如下圖(以fun(int var1,int var2,...,int var3,int var4)為例):
棧區(qū):
|棧頂 低地址
|第一個(gè)固定參數(shù)var1
|可變參數(shù)前的第一個(gè)固定參數(shù)var2
|可變參數(shù)的第一個(gè)參數(shù)
|...
|可變參數(shù)的最后一個(gè)參數(shù)
|函數(shù)的倒數(shù)第二個(gè)固定參數(shù)var3
|函數(shù)的最后一個(gè)固定參數(shù)var4
|...
|函數(shù)的返回地址
|...
|棧底 高地址
2)使用可變參數(shù)所用到頭文件和相關(guān)宏說明
在此,以TC2.0編譯器為參考對(duì)象來說明.
可變參數(shù)的相關(guān)定義在TC2.0的名為"STDARG.H"的頭文件中.
此文件為:
/* stdarg.h
Definitions for ACCESSing parameters in functions that accept
a variable number of arguments.
Copyright (c) Borland International 1987,1988
All Rights Reserved.
*/
#if __STDC__
#define _Cdecl
#else
#define _Cdecl cdecl
#endif
#if !defined(__STDARG)
#define __STDARG
typedef void *va_list;
#define va_start(ap, parmN) (ap = ...)
#define va_arg(ap, type) (*((type *)(ap))++)
#define va_end(ap)
#define _va_ptr (...)
#endif
以上為"STDARG.H"的內(nèi)容.
該文件定義了使用可變參數(shù)所用到的數(shù)據(jù)類型:typedef void *va_list;
va_start(ap,parmN)起到初始化,使用得ap指向可變參數(shù)的第一個(gè)參數(shù).ap的類型為va_list,
parmN為可變參數(shù)的前面一個(gè)固定參數(shù).
va_arg(ap,type)獲得當(dāng)前ap所指向的參數(shù),并使ap指向可變參數(shù)的下一個(gè)參數(shù),type為需要獲得的參數(shù)的類型.
va_end(ap) 結(jié)束可變參數(shù)獲取.
3)可變參數(shù)的使用實(shí)例
實(shí)例目的:用可變參數(shù)來實(shí)現(xiàn)個(gè)數(shù)不定的字符串的傳遞,并顯示傳遞過來的字符串.
#include
#include
#include
void tVarArg(int num,...);/*num為可變參數(shù)的個(gè)數(shù)*/
int main(void)
{
clrscr();
tVarArg(5,"Hello! ","My ","name ","is ","neverTheSame.\n");
tVarArg(8,"This ","is ","an ","example ","about ","variable-argument ","in ","funtion");
getch();
return 0;
}
void tVarArg(int num,...)
{
va_list argp; /*定義一個(gè)指向可變參數(shù)的變量*/
va_start(argp,num); /*初始化,使用argp指向可變參數(shù)的第一個(gè)參數(shù)*/
while(--num>=0)
printf("%s",(va_arg(argp,char*)));/*va_arg(argp,char*)獲得argp所指向的參數(shù),
并使用argp指向下一個(gè)參數(shù),char*使用所獲得的參數(shù)的類型轉(zhuǎn)換為char*型.*/
va_end(argp); /*結(jié)束可變參數(shù)獲取*/
return ;
}
4)可變參數(shù)的使用需要注意的問題
1.每個(gè)函數(shù)的可變參數(shù)至多有一個(gè).
2.va_start(ap,parmN)中parmN為可變參數(shù)前的一個(gè)固定參數(shù).
3.可變參數(shù)的個(gè)數(shù)不確定,完全由程序約定.
4.可變參數(shù)的類型不確定,完全由va_arg(ap,type)中的type指定,然后就把參數(shù)的類型強(qiáng)制轉(zhuǎn)換.
而printf()中不是實(shí)現(xiàn)了識(shí)別參數(shù)嗎?那是因?yàn)楹瘮?shù)
printf()是從固定參數(shù)format字符串來分析出參數(shù)的類型,再調(diào)用va_arg
的來獲取可變參數(shù)的.也就是說,你想實(shí)現(xiàn)智能識(shí)別可變參數(shù)的話是要通
過在自己的程序里作判斷來實(shí)現(xiàn)的.
5.編譯器對(duì)可變參數(shù)的函數(shù)的原型檢查不夠嚴(yán)格,對(duì)編程人員要求很高.
它在函數(shù)的定義時(shí),用三個(gè)點(diǎn)號(hào)'.'表示,用逗號(hào)與其它參數(shù)分隔.
可變參數(shù)的特點(diǎn):不像固定參數(shù)那樣一一對(duì)應(yīng),也不像固定參數(shù)有固定的參數(shù)類型和參數(shù)名稱;可變參數(shù)中個(gè)數(shù)不
定可是傳入的是一個(gè)參數(shù)也可以是多個(gè);可變參數(shù)中的每個(gè)參數(shù)的類型可以不同,也可以相同;可變參數(shù)的每個(gè)參數(shù)并沒有
實(shí)際的名稱與之相對(duì)應(yīng).
由此可見,可變參數(shù)的形式非常自由而富有彈生.因些,它給那些天才程序員有更大地想象和發(fā)揮空間.
然而,更多地自由,同樣也加大操作上的難度.
以下就對(duì)可變參數(shù)的幾個(gè)方面作一定的介紹.
1)可變參數(shù)的存儲(chǔ)形式.
大家都知道,一般函數(shù)的形參屬于局部變量.而局部變量就是存儲(chǔ)在內(nèi)存的棧區(qū)(所謂的棧區(qū):由編譯器自動(dòng)分配釋放,
存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。).可變參數(shù)也是存儲(chǔ)在內(nèi)存棧區(qū).
在對(duì)函數(shù)的形參存儲(chǔ)的時(shí)侯,編譯器是從函數(shù)的形參的右邊到左邊逐一地壓棧,
這樣保證了棧頂是函數(shù)的形參的第一個(gè)參數(shù)(從左到右數(shù)).而80x86平臺(tái)下的內(nèi)存分配順序是從高地址內(nèi)存到低地址內(nèi)存.
因此,函數(shù)的形參在內(nèi)存的存儲(chǔ)形式如下圖(以fun(int var1,int var2,...,int var3,int var4)為例):
棧區(qū):
|棧頂 低地址
|第一個(gè)固定參數(shù)var1
|可變參數(shù)前的第一個(gè)固定參數(shù)var2
|可變參數(shù)的第一個(gè)參數(shù)
|...
|可變參數(shù)的最后一個(gè)參數(shù)
|函數(shù)的倒數(shù)第二個(gè)固定參數(shù)var3
|函數(shù)的最后一個(gè)固定參數(shù)var4
|...
|函數(shù)的返回地址
|...
|棧底 高地址
2)使用可變參數(shù)所用到頭文件和相關(guān)宏說明
在此,以TC2.0編譯器為參考對(duì)象來說明.
可變參數(shù)的相關(guān)定義在TC2.0的名為"STDARG.H"的頭文件中.
此文件為:
/* stdarg.h
Definitions for ACCESSing parameters in functions that accept
a variable number of arguments.
Copyright (c) Borland International 1987,1988
All Rights Reserved.
*/
#if __STDC__
#define _Cdecl
#else
#define _Cdecl cdecl
#endif
#if !defined(__STDARG)
#define __STDARG
typedef void *va_list;
#define va_start(ap, parmN) (ap = ...)
#define va_arg(ap, type) (*((type *)(ap))++)
#define va_end(ap)
#define _va_ptr (...)
#endif
以上為"STDARG.H"的內(nèi)容.
該文件定義了使用可變參數(shù)所用到的數(shù)據(jù)類型:typedef void *va_list;
va_start(ap,parmN)起到初始化,使用得ap指向可變參數(shù)的第一個(gè)參數(shù).ap的類型為va_list,
parmN為可變參數(shù)的前面一個(gè)固定參數(shù).
va_arg(ap,type)獲得當(dāng)前ap所指向的參數(shù),并使ap指向可變參數(shù)的下一個(gè)參數(shù),type為需要獲得的參數(shù)的類型.
va_end(ap) 結(jié)束可變參數(shù)獲取.
3)可變參數(shù)的使用實(shí)例
實(shí)例目的:用可變參數(shù)來實(shí)現(xiàn)個(gè)數(shù)不定的字符串的傳遞,并顯示傳遞過來的字符串.
#include
#include
#include
void tVarArg(int num,...);/*num為可變參數(shù)的個(gè)數(shù)*/
int main(void)
{
clrscr();
tVarArg(5,"Hello! ","My ","name ","is ","neverTheSame.\n");
tVarArg(8,"This ","is ","an ","example ","about ","variable-argument ","in ","funtion");
getch();
return 0;
}
void tVarArg(int num,...)
{
va_list argp; /*定義一個(gè)指向可變參數(shù)的變量*/
va_start(argp,num); /*初始化,使用argp指向可變參數(shù)的第一個(gè)參數(shù)*/
while(--num>=0)
printf("%s",(va_arg(argp,char*)));/*va_arg(argp,char*)獲得argp所指向的參數(shù),
并使用argp指向下一個(gè)參數(shù),char*使用所獲得的參數(shù)的類型轉(zhuǎn)換為char*型.*/
va_end(argp); /*結(jié)束可變參數(shù)獲取*/
return ;
}
4)可變參數(shù)的使用需要注意的問題
1.每個(gè)函數(shù)的可變參數(shù)至多有一個(gè).
2.va_start(ap,parmN)中parmN為可變參數(shù)前的一個(gè)固定參數(shù).
3.可變參數(shù)的個(gè)數(shù)不確定,完全由程序約定.
4.可變參數(shù)的類型不確定,完全由va_arg(ap,type)中的type指定,然后就把參數(shù)的類型強(qiáng)制轉(zhuǎn)換.
而printf()中不是實(shí)現(xiàn)了識(shí)別參數(shù)嗎?那是因?yàn)楹瘮?shù)
printf()是從固定參數(shù)format字符串來分析出參數(shù)的類型,再調(diào)用va_arg
的來獲取可變參數(shù)的.也就是說,你想實(shí)現(xiàn)智能識(shí)別可變參數(shù)的話是要通
過在自己的程序里作判斷來實(shí)現(xiàn)的.
5.編譯器對(duì)可變參數(shù)的函數(shù)的原型檢查不夠嚴(yán)格,對(duì)編程人員要求很高.

