讀古今文學網 > C語言解惑 > 20.6 探討printf函數 >

20.6 探討printf函數

可能大家已經注意到,printf函數不存在任何內建的方式來得知給定的參數數目。使用stdarg系列的宏的每個程序都有責任通過確立某種約定或慣例來標誌參數列表的約束。這裡的printf函數的第1個參數必須是一個格式字符串,通過檢查這個字符串來得到其餘參數的數目與類型。所以關鍵就是實現printf函數用以存取變長參數列表的機制。這種機制應該擁有以下特性:

(1)只需要知道函數的第1個參數的類型,就可以對其進行存取。

(2)一旦第n個參數被成功存取,第n+1個參數就可以在僅知道類型的情況下進行存取。

(3)按這種方式存取一個參數所需要的時間不應太多。

需要特別注意的是:逆向存取參數,或者隨機存取參數,或者以任何非從頭到尾的順序方式存取參數,都是不必要的。進一步來說,既不必要檢測參數列表是否結束,也不可能。

這些信息存儲在一個類型為va_list的變量中。因此,聲明一個名稱為ap的類型為va_list的變量後,只需要給定ap與第1個參數的類型就可以確定第1個參數的值。

通過va_list存取一個參數之後,將更新va_list,指向參數列表中的下一個參數。

因為一個va_list中包括了存取全部參數的所有必要信息,所以一個函數g可以為它的參數創建一個va_list,然後把它傳遞給另一個函數。這樣,這個函數就能夠訪問到函數g的參數。

【例20.26】演示使用stdarg.h編寫的printf函數的例子。


#include <stdarg.h>
int printf
( const char *format
, ... 
)
{
        int n
;
        va_list ap
;
        va_start
( ap
, format 
);
        n = vprintf
( format 
, ap
);
        va_end
(ap
);
        return n
;
 }
  

第二篇第13章的debug和error函數都是根據這個原理編製的,這裡就不再舉例驗證了。