va_list 是c語言中解決變長引數問題的一組巨集
va_list的用法:
(1)首先在函式裡定義乙個va_list型別的變數,這個變數是指向引數的指標;
(2)然後用va_start巨集初始化剛定義的va_list變數,這個巨集的第二個引數是第乙個可變引數的前乙個引數,是乙個固定的引數;
(3)然後用va_arg返回可變的引數,va_arg的第二個引數是你要返回的引數的型別,如果函式有多個可變引數的,依次呼叫va_arg獲取各個引數;
(4)最後用va_end巨集結束可變引數的獲取。
va_list在編譯器中的處理:
(1)在執行va_start(ap,v)以後,ap指向第乙個可變引數在堆疊的位址;
(2)va_arg()取得型別t的可變引數值,在這步操作中首先apt = sizeof(t型別),讓ap指向下乙個引數的位址。然後返回ap-sizeof(t型別)的t型別*指標,這正是第乙個可變引數在堆疊裡的位址。然後用*取得這個位址的內容;
(3)va_end(),x86平台定義為ap = ((char*)0),使ap不再指向堆疊,而是跟null一樣,有些直接定義為((void*)0),這樣編譯器不會為va_end產生**,例如gcc在linux的x86平台就是這樣定義的。
要注意的是:由於引數的位址用於va_start巨集,所以引數不能宣告為暫存器變數、函式或陣列型別。
使用va_list應該注意的問題:
(1)因為va_start, va_arg, va_end等定義成巨集,所以它顯得很愚蠢,可變引數的型別和個數完全在該函式中由程式**控制,它並不能智慧型地識別不同引數的個數和型別.也就是說,你想實現智慧型識別可變引數的話是要通過在自己的程式裡作判斷來實現的;
(2)另外有乙個問題,因為編譯器對可變引數的函式的原型檢查不夠嚴格,對程式設計查錯不利.不利於我們寫出高質量的**。
小結:可變引數的函式原理其實很簡單,而va系列是以巨集定義來定義的,實現跟堆疊相關。我們寫乙個可變函式的c函式時,有利也有弊,所以在不必要的場合,我們無需用到可變引數,如果在c++裡,我們應該利用c++多型性來實現可變引數的功能,盡量避免用c語言的方式來實現。
/*********************************補充材料*********************************************/
涉及頭檔名:#include c++中;
函式名: vfprintf
功 能: 格式化的資料輸出到指定的資料流中
用 法: int vfprintf(file *stream, char *format, va_list param);
函式說明:vfprintf()會根據引數format字串來轉換並格式化資料,然後將結果輸出到引數stream指定的檔案中,直到出現字串結束(『\0』)為止。關於引數format字串的格式請參 考printf()。
返回值:成功則返回實際輸出的字元數,失敗則返回-1,錯誤原因存於errno中。
例子:寫乙個簡單的可變引數的c函式
下面我們來**如何寫乙個簡單的可變引數的c函式.寫可變引數的c函式要在程式中用到以下這些巨集:
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
va在這裡是variable-argument(可變引數)的意思。
這些巨集定義在stdarg.h中,所以用到可變引數的程式應該包含這個標頭檔案。
下面我們寫乙個簡單的可變引數的函式,改函式至少有乙個整數引數,第二個引數也是整數,是可選的.函式只是列印這兩個引數的值。
void ******_va_fun(int i, ...)
C語言變長引數實現
include include include 編寫可變長引數列表的函式案例 void minprintf char fmt,這個函式只處理格式字串和引數,格式的轉換則通過printf函式實現 省略號表示引數的數量和型別是可變的,省略號只能出現再參數列的尾部,minprintf不需要像printf ...
C語言可變長引數
在使用可變長引數時發現的乙個問題,首先先放一段 和它的執行結果 產生這樣結果的原因就在於va start的第二個引數不同 原先一直以為va start的第二個引數是引數的個數,查了一些資料,找到va start的定義後發現,va start的第二個引數是可變長引數最左邊的位址。va start的定義...
C語言中變長引數例項
include include define sum arg.sum my name is arg char sum char a,變長引數的實現基於的是 c 語言預設的 cdecl 呼叫慣例中 自右向左壓棧的傳遞方式 比如 sum a,b,c 的各個引數在 棧中的相對順序為 top of stac...