為了解決這些問題,我們首先要解釋cdecl呼叫約定(參見論調用約定),所有使用不定引數的函式必須是使用cdecl(全域性函式)或者this call(類成員函式)呼叫約定。該約定對於引數傳遞規定如下:
引數從右向左入棧(也就是如果你呼叫f(a,b,c),則c先入棧,然後是b,最後是a入棧)
呼叫者負責清理堆疊
在設計具有不定引數列表的函式的時候,我們有兩種方法來確定到底多少引數會被傳遞進來。
方法1是在型別固定的引數中指明後面有多少個引數以及他們的型別。printf就是採用的這種方法,它的format引數指明後面每個引數的型別。
方法2是指定乙個結束引數。這種情況一般是不定引數擁有同樣的型別,我們可以指定乙個特定的值來表示引數列表結束。
#include "stdarg.h"
using
namespace
std;
intsum(
intcount, ...)
va_end(args);
return
sum_value;
} int
_tmain(
intargc, _tchar* argv)
在vc6,va_start函式定義為:
_intsizeof(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define
va_start(ap,v) ( ap = (va_list)&v + _intsizeof(v) )
其中_intsizeof(n)計算比n大的sizeof(int)的最小倍數,如果n=101,則_intsizeof(n)為104。
va_start執行完畢後,ap指向變數v後第乙個4位元組對齊的位址。例如,v的位址為0x123456, v的大小為13,則v後面的下乙個與字邊界對齊的位址為0x123456+0x0d=0x123463再調整為與4位元組對齊的下乙個位址,也就是 0x123464.
va_arg函式定義為:
va_arg(ap,t) ( *(t *)((ap += _intsizeof(t)) - _intsizeof(t)) )
分析與va_start一樣,它的結果是使ap指向當前變數的下乙個變數。
這樣,我們只要在開始時使用va_start把不定引數列表賦值給ap,然後依次用va_arg獲得不同引數即可。
C C 可變引數
函式 使用va list巨集組解決變參問題 1 首先定義va list型的變數,這個變數是指向引數的指標。2 然後用va start巨集初始化剛定義的va list變數,這個巨集的第二個引數是 第乙個可變引數的前乙個引數 3 再用va arg得到可變引數,第二個引數是 可變引數 的型別。4 最後用v...
C C 可變引數
函式 使用va list巨集組解決變參問題 1 首先定義va list型的變數,這個變數是指向引數的指標。2 然後用va start巨集初始化剛定義的va list變數,這個巨集的第二個引數是 第乙個可變引數的前乙個引數 3 再用va arg得到可變引數,第二個引數是 可變引數 的型別。4 最後用v...
c c 可變引數
c語言支援在函式定義時,用 省略號代表可變引數列表,中最常見的可變引數的例子是printf引數,c 的可變引數繼承自c。可變引數的引數列表在壓棧時,同一組引數是按照從右向左的順序,逐個由高位址向低位址壓倒棧中。知道到最左邊乙個引數的位址 型別和右邊每個引數的型別,就可以計算出每乙個引數的位址,這是可...