| 宏 | 作用 | 參數 |
va_list | 聲明參數列表指針 | 不透明類型(通常 char*) |
va_start(ap, last) | 初始化 ap 指向第一個可變參數 | last 為最後一個固定參數名 |
va_arg(ap, type) | 取出當前參數並按 type 大小移動指針 | 需知參數類型 |
va_end(ap) | 清理(某架構調整棧指針) | 必須成對調用 |
示例 1:求 N 個數之和
int sum(int count, ...) {
int s = 0; va_list ap;
va_start(ap, count);
for (int i = 0; i < count; ++i)
s += va_arg(ap, int);
va_end(ap);
return sum;
}
// 調用:sum(5, 1,2,3,4,5) → 15
示例 2:標準庫可變參數函數族
void test(int count, ...) {
va_list ap; va_start(ap, count);
vprintf("%d,%d,%d\n", ap); // 格式化輸出
char buf[1024];
vsprintf(buf, "a=%d,b=%d,c=%d\n", ap); // 格式化到緩衝區
vfprintf(stdout, "a=%d,b=%d,c=%d\n", ap); // 輸出到流
vsscanf("10,30,40", "%d,%d,%d", ap); // 從字符串掃描到可變參數地址
vsnprintf(buf, 30, "a=%d,b=%d,c=%d", ap); // 限長格式化
va_end(ap);
}
關鍵注意點
- **類型一致性**:
va_arg 類型必須與實際參數類型完全匹配(含符號、寬度),否則 UB。
- **參數個數**:需約定機制(如首參數計數、哨兵值、格式字符串)告知函數何時停止。
- **棧帧佈局**:參數右至左入棧,
va_start 以最後固定參數地址為基準計算偏移。
- **可移植性**:
va_list 在某些架構(如 x86_64)是結構體而非指針,不可假設為指針操作。
掌握 stdarg.h 是實現 printf、日志庫、腳本綁定等基礎設施的前提。
- 上一篇文章: CSAPP 2.20 習題解析:T2U 公式驗證
- 下一篇文章: C99 可變參數宏 __VA_ARGS__ 實戰:調試日志開關與 Android NDK 應用
Copyright ©
程式碼之家 All Rights Reserved