C 語言通過 <stdarg.h> 提供可變參數機制,支撐 printf、scanf 等標準庫函數。本文詳細講解四大宏的使用規則與實戰案例。
| 宏/類型 | 作用 | 參數說明 |
|---|---|---|
va_list | 參數列表指針類型 | 聲明一個變量用於遍歷參數 |
va_start(ap, last) | 初始化參數列表 | last 為最後一個固定參數名 |
va_arg(ap, type) | 提取下一個參數 | type 為期望的參數類型 |
va_end(ap) | 清理參數列表 | 必須調用,否則未定義行為 |
float avg(int count, ...)va_list ap;va_start(ap, count);va_arg(ap, type) 獲取參數va_end(ap); 結束#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>
float average(int n_values, ...) {
va_list ap;
va_start(ap, n_values);
float sum = 0;
for (int i = 0; i < n_values; i++) {
sum += va_arg(ap, int); // 假設傳入 int,自動提升為 float
}
va_end(ap);
return sum / n_values;
}
int main() {
printf("%.2f\n", average(6, 1, 2, 3, 4, 5, 6)); // 3.50
return 0;
}
void nstrcpy(char *dest, ...) {
va_list ap;
va_start(ap, dest);
char *p;
while ((p = va_arg(ap, char *)) != NULL) { // 以 NULL 結束
strcpy(dest, p);
dest += strlen(p);
}
va_end(ap);
*dest = '\0';
}
int main() {
char buf[100];
nstrcpy(buf, "Hello", " ", "World", "!", NULL);
printf("%s\n", buf); // Hello World!
return 0;
}
va_arg 類型,需自行保證調用端一致float → double,char/short → int,取用時用提升後類型va_list 可能是結構體或指針,不可假設可直接賦值複製va_copy(dest, src) 安全複製參數列表void my_printf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
while (*fmt) {
if (*fmt == '%') {
fmt++;
switch (*fmt) {
case 'd': printf("%d", va_arg(ap, int)); break;
case 's': printf("%s", va_arg(ap, char *)); break;
case 'f': printf("%f", va_arg(ap, double)); break;
case 'c': printf("%c", va_arg(ap, int)); break;
}
} else {
putchar(*fmt);
}
fmt++;
}
va_end(ap);
}