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

C/C++ 可變參數函式完整實作指南

     編輯:關於C++

可變參數函式允許參數個數動態決定,C 語言強大特性之一(Fortran 等語言不支援)。典型範例:printf()、scanf()。

實作原理:C 語言呼叫慣例 __cdecl

  • 參數**從右至左入栈**,個數可變
  • 函式本體無法預知參數個數 → **由呼叫者負責清理堆疊**
  • 範例組合語言展示 push 順序與 add esp, 8 清理堆疊

標準巨集支援

stdarg.h (ANSI) / varargs.h (Unix 相容) 定義巨集屏蔽平台差異:


typedef char * va_list;
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
#define va_start(ap,v) (ap = (va_list)&v + _INTSIZEOF(v))
#define va_arg(ap,t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
#define va_end(ap) (ap = (va_list)0)

_INTSIZEOF 確保整數位元組對齊。

函式宣告語法

  • ANSI:type funcname(type para1, type para2, ...); 至少一個固定參數,... 為語法一部分
  • Unix 相容:type funcname(va_alist); va_dcl 無需固定參數
  • 建議使用 stdarg.h ANSI 標準,可移植性最佳

基本使用範例


// 範例1:字串列表處理
int demo(char *msg, ...) {
    va_list argp; int argno = 0; char *para;
    va_start(argp, msg);  // msg 為最後一個固定參數
    while (1) {
        para = va_arg(argp, char*);
        if (strcmp(para, "\0") == 0) break;  // 空串作結束標記
        printf("參數 #%d 是: %s\n", argno++, para);
    }
    va_end(argp); return 0;
}

// 範例2:計算平均值
int average(int first, ...) {
    int count = 0, sum = 0, i = first;
    va_list marker;
    va_start(marker, first);
    while (i != -1) {  // -1 作結束標記
        sum += i; count++;
        i = va_arg(marker, int);
    }
    va_end(marker);
    return sum ? (sum / count) : 0;
}

參數傳遞給其他可變參數函式的難題

無法直接將 va_list 傳給 printf 等函式(僅傳遞指標值而非完整堆疊內容)。printf 內部實作透過 _output(stdout, format, arglist) 處理。

解決方案:逐個 va_arg 解析後再逐個呼叫,或自行解析格式字串對應參數類型(範例程式碼示範簡易版 mywrite 解析 %d/%f 並呼叫 printf)。

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