不定參數函數 stdarg.h是C語言中C标準函數庫的頭檔案,stdarg是由stdandard(标準) arguments(參數)簡化而來,主要目的為讓函數能夠接收不定量參數。 C++的cstdarg頭檔案中也提供這樣的機能;雖然與C的頭檔案是相容的,但是也有沖突存在。 不定參數函數(Variadic functions)是stdarg.h内容典型的應用,雖然也可以使用在其他由不定參數函數調用的函數(例如,vprintf)。
聲明不定參數函數 不定參數函數的參數數量是可變動的,它使用省略号來忽略之後的參數。例如printf函數一般。代表性的聲明為: int check(int a, double b, ...); 不定參數函數最少要有一個命名的參數,是以 char *wrong(...); 在C是不被允許的(在C++中,這樣的聲明是合理的)。在C,省略符号之前必須要有逗号;在C++,則沒有這種強制要求。
定義不定參數函數 使用相同的文法來定義: long func(char, double, int, ...); long func(char a, double b, int c, ...) { } 在舊形式可能會出現較省略的函數定義: long func(); long func(a, b, c, ...) char a; double b; { }
通路參數 通路未命名的參數,首先必須在不定參數函數中聲明va_list型态的變數。調用va_start并傳入兩個參數:第一個參數為va_list型态的變數,第二個為函數最後一個參數的名稱,接着每一調用va_arg就會回傳下一個參數,va_arg的第一個參數為va_list,第二個參數為回傳的型态。最後va_end必須在函數回傳前被va_list呼叫(當作參數)。(沒有要求要讀取完所有參數) C99提供額外的巨集,va_copy,它能夠複制va_list。而va_copy(va2, va1)意思為拷貝va1到va2。 沒有機制定義該怎麼判别傳遞到函數的參數量或者型态。函數通常需要知道或确定它們變化的方法。共通的慣例包含: 使用printf或scanf類的格式化字元串來嵌入明确指定的型态。 在不定參數最後的标兵值(sentinel value)。 總數變數來指明不定參數的數量.
類型安全性 有些C工具将C擴充允許編譯器檢查适當格式化字元串及标兵(sentinels)的使用。如果沒有這個擴充,編譯器通常無從檢查傳入函數的未命名參數是否為所預期的型态。是以,必須對點做出謹慎的正确性确認,型态沒有吻合為未定義行為(Undefined behavior)。舉個例,如果傳入NULL指針,首先就是不能寫入對應到适當指針型态但純粹NULL的指針。再者考慮預設參數應用到未命名參數。float将會自動的被轉換成double‧同樣的比int(整數)更小容量的參數型态将會被轉換成int或者unsigned int‧函數所接收到的未命名參數必須預期到會被轉換型态。
例子 #include <stdarg.h> #include <stdio.h>
int sum(int n,...) { int sum = 0; va_list arg_ptr; va_start(arg_ptr,n); for(;n;--n) { sum = sum + va_arg(arg_ptr,int); } va_end(arg_ptr);
return sum; }
int main(int argc,const char* argv[]) { printf("sum: %i\n",sum(3,1,2,3)); return 0; }