C 語言通過 `
| 名稱 | 類型 | 作用 |
|---|---|---|
va_list | 類型 | 保存可變參數列表信息的不透明對象 |
va_start(ap, last) | 宏 | 初始化 ap,使其指向第一個可變參數(last 為最後一個固定參數名) |
va_arg(ap, type) | 宏 | 按 type 取出下一個參數,並推進 ap |
va_end(ap) | 宏 | 清理 ap,函數返回前必須調用 |
va_copy(dest, src) | 宏(C99) | 複製 va_list,避免多次遍歷污染 |
int func(int fixed, ...);
#include
#include
void PrintFloats(int amount, ...) {
va_list ap;
va_start(ap, amount);
printf("Floats passed: ");
for (int i = 0; i < amount; i++) {
double val = va_arg(ap, double); // 默認參數提升:float -> double
printf("\t%.2f", val);
}
va_end(ap);
printf("\n");
}
int main() {
PrintFloats(3, 3.14159, 2.71828, 1.41421);
return 0;
}
// 輸出: Floats passed: 3.14 2.72 1.41
int FindMax(int amount, ...) {
va_list ap;
va_start(ap, amount);
int max = va_arg(ap, int); // 至少有一個參數
for (int i = 1; i < amount; i++) {
int val = va_arg(ap, int);
if (val > max) max = val;
}
va_end(ap);
return max;
}
int main() {
printf("Max: %d\n", FindMax(7, 702, 422, 631, 834, 892, 104, 772)); // 892
return 0;
}
void PrintLines(char *first, ...) {
va_list ap;
va_start(ap, first);
char *str = first;
do {
printf("%s\n", str);
str = va_arg(ap, char *);
} while (str != NULL); // 以 NULL 指針作為結束標記
va_end(ap);
}
int main() {
PrintLines("First", "Second", "Third", "Fourth", NULL);
return 0;
}
void foo(int n, ...) {
va_list ap, ap2;
va_start(ap, n);
va_copy(ap2, ap); // 備份
// 第一次遍歷...
va_end(ap);
// 第二次遍歷用 ap2...
va_end(ap2);
}
C++11 起推薦使用 Variadic Templates + `std::initializer_list` / 折疊表達式,類型安全、編譯期展開,避免運行期解析開銷與 UB 風險。
掌握 `stdarg.h` 機制是閱讀標準庫源碼、編寫通用工具函數(日誌、格式化、腳本綁定)的基礎。核心口訣:一啟動、二取參、三清理、四約定個數類型、五小心提升陷阱。