首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C 語言可變參數完整指南:va_list、va_start、va_arg、va_end 與實戰封裝

     編輯:關於C

核心 API(<stdarg.h>)

宏/類型作用
va_list參數列表指針類型
va_start(ap, last_fixed)初始化 ap 指向第一個可變參數
va_arg(ap, type)取出下一個參數,按 type 大小移動 ap
va_end(ap)清理 ap(某些平台需調用)
va_copy(dest, src)C99:複製參數列表,避免二次遍歷失效

基礎示例:求和函數

#include 
#include 

int sum(int count, ...) {
    va_list ap;
    va_start(ap, count);
    int total = 0;
    for (int i = 0; i < count; i++)
        total += va_arg(ap, int);
    va_end(ap);
    return total;
}

int main() {
    printf("10+20+30 = %d\n", sum(3, 10, 20, 30));
    printf("4+20+25+30 = %d\n", sum(4, 4, 20, 25, 30));
    return 0;
}

進階封裝:類 printf 格式化輸出

void my_log(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);  // 標準庫 vprintf 直接消費 va_list
    va_end(ap);
}

/* 帶級別、文件、行號 */
void log_ex(int level, const char *file, int line, const char *fmt, ...) {
    static const char *prefix[] = {"[DEBUG]", "[INFO]", "[WARN]", "[ERROR]"};
    fprintf(stderr, "%s %s:%d ", prefix[level], file, line);
    va_list ap;
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);
    fputc('\n', stderr);
}
#define LOG_INFO(fmt, ...) log_ex(1, __FILE__, __LINE__, fmt, ##__VA_ARGS__)

關鍵注意事項

陷阱說明對策
無參數個數信息va_arg 不知道何時停止約定:首參數為 count / 格式串 / 哨兵值
類型不匹配va_arg(int) 實傳 double → UB嚴格按聲明類型傳遞,或用 _Generic (C11)
二次遍歷失效va_list 可能為一次性迭代器用 va_copy 複製副本
默認參數提升float→double, char/short→intva_arg 取提升後類型
可變參數不能為引用/非 PODC++ 類對象傳值語義C++ 用 variadic templates 替代

實戰:簡易錯誤報告宏

#define ERR_RETURN(cond, fmt, ...) do { \
    if (cond) { \
        fprintf(stderr, "[ERR] %s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
        return -1; \
    } \
} while(0)

/* 使用 */
int read_file(const char *path) {
    FILE *fp = fopen(path, "r");
    ERR_RETURN(!fp, "Cannot open %s", path);
    /* ... */
    return 0;
}

總結

va_list 系列是 C 語言實現可變參數的基石。掌握「初始化 → 逐個提取 → 清理」流程,理解默認參數提升、哨兵約定、va_copy,即可編寫健壯的日志、格式化、錯誤處理等通用工具。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved