變長參數(Variadic Functions)是 C 語言實現 printf、scanf 等格式化輸入輸出的核心機制。《精通 Unix 下 C 語言程式設計與專案實踐》系統講解了 stdarg.h 標準宏的使用流程、參數傳遞技巧與實戰範例。
返回類型 函數名(固定參數1, 固定參數2, ...);
... 必須置於參數列表最右端va_start 定位基準int printf(const char *format, ...);va_list ap; // 訪問變長參數列表的物件
va_start(ap, last_fixed_param);
根據最後一個固定參數位置,定位變長參數起始地址。
範例:func(int n, ...) → va_start(ap, n);
type val = va_arg(ap, type);
每次呼叫自動推進到下一個參數。型別必須與實際傳入匹配,否則行為未定義。
範例:va_arg(ap, int)、va_arg(ap, double)
va_end(ap);
結束訪問,釋放相關資源(某些實作為空操作,但習慣上必須配對呼叫)。
int mysum(int count, ...) {
int sum = 0;
va_list ap;
va_start(ap, count);
for (int i = 0; i < count; i++)
sum += va_arg(ap, int);
va_end(ap);
return sum;
}
// 呼叫
mysum(1, 4); // 4
mysum(2, 4, 8); // 12
// 第一個參數傳遞後續參數個數,是常見約定
若需將「...」整體傳給另一函數,不可直接傳 va_list 變數(因 va_arg 會改變其內部狀態),而應使用 vprintf、vfprintf、vsprintf 等對應函數:
int PrintLog(FILE *stream, const char *fmt, ...) {
if (!stream || !fmt) return -1; // 防禦性程式設計:檢查指標有效性
va_list ap;
va_start(ap, fmt);
char buf[1024];
vsprintf(buf, fmt, ap); // 將格式化結果寫入緩衝區
va_end(ap);
return fputs(buf, stream);
}
NULL,避免空指標解引用崩潰... 型別,需透過格式字串或計數參數自行保證va_list 不能重複遍歷,需透傳時用 v* 族函數vsprintf 無長度檢查,生產環境建議改用 vsnprintf變長參數雖屬進階特性,但掌握其標準流程與防禦性寫法,能讓你設計出靈活易用的 API(如日誌庫、格式化工具),是 C 程式設計師進階的關鍵技能。