可變參數函式允許參數個數動態決定,C 語言強大特性之一(Fortran 等語言不支援)。典型範例:printf()、scanf()。
push 順序與 add esp, 8 清理堆疊stdarg.h (ANSI) / varargs.h (Unix 相容) 定義巨集屏蔽平台差異:
typedef char * va_list;
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
#define va_start(ap,v) (ap = (va_list)&v + _INTSIZEOF(v))
#define va_arg(ap,t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
#define va_end(ap) (ap = (va_list)0)
_INTSIZEOF 確保整數位元組對齊。
type funcname(type para1, type para2, ...); 至少一個固定參數,... 為語法一部分type funcname(va_alist); va_dcl 無需固定參數stdarg.h ANSI 標準,可移植性最佳
// 範例1:字串列表處理
int demo(char *msg, ...) {
va_list argp; int argno = 0; char *para;
va_start(argp, msg); // msg 為最後一個固定參數
while (1) {
para = va_arg(argp, char*);
if (strcmp(para, "\0") == 0) break; // 空串作結束標記
printf("參數 #%d 是: %s\n", argno++, para);
}
va_end(argp); return 0;
}
// 範例2:計算平均值
int average(int first, ...) {
int count = 0, sum = 0, i = first;
va_list marker;
va_start(marker, first);
while (i != -1) { // -1 作結束標記
sum += i; count++;
i = va_arg(marker, int);
}
va_end(marker);
return sum ? (sum / count) : 0;
}
無法直接將 va_list 傳給 printf 等函式(僅傳遞指標值而非完整堆疊內容)。printf 內部實作透過 _output(stdout, format, arglist) 處理。
解決方案:逐個 va_arg 解析後再逐個呼叫,或自行解析格式字串對應參數類型(範例程式碼示範簡易版 mywrite 解析 %d/%f 並呼叫 printf)。