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

C語言可變參數列表 詳解:va_list、va_start、va_arg、va_end 實戰

     編輯:關於C語言

C語言可變參數列表 詳解:va_list、va_start、va_arg、va_end 實戰

C 語言通過 <stdarg.h> 提供可變參數機制,支撐 printf、scanf 等標準庫函數。本文詳細講解四大宏的使用規則與實戰案例。

核心宏與類型

宏/類型作用參數說明
va_list參數列表指針類型聲明一個變量用於遍歷參數
va_start(ap, last)初始化參數列表last 為最後一個固定參數名
va_arg(ap, type)提取下一個參數type 為期望的參數類型
va_end(ap)清理參數列表必須調用,否則未定義行為

使用流程規範

  1. 函數簽名以省略號結尾:float avg(int count, ...)
  2. 聲明 va_list ap;
  3. 調用 va_start(ap, count);
  4. 循環調用 va_arg(ap, type) 獲取參數
  5. 調用 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 類型,需自行保證調用端一致
  • 參數個數確定:需通過固定參數(如 count)、格式字符串、哨兵值(NULL/-1)傳遞
  • 默認參數提升:float → double,char/short → int,取用時用提升後類型
  • 可移植性:va_list 可能是結構體或指針,不可假設可直接賦值複製
  • C99 新增:va_copy(dest, src) 安全複製參數列表

實現類 printf 簡化版

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);
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved