VARARGS,STDARGS,可變參數列表摘要

一、是否可以只使用一組整數參數來複制任意類型的數值?(理論上,只要函數參數個數支持,這僅是對內存解釋的不同)

 

關於Printf的實現 第一個參數必須是一個字符串。//??

1.在知道第一個參數類型的情況下,就可以對其進行存取。

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

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

 

大多數c語言都是通過一組VARARGS來實現上述目的。

 

帶有可變參數列表的函數,必須在函數定義的首部使用va_alist和va_dcl 宏。

#include<vararg.h>

void error (va_alist) va_dcl

 

varargs.h的一個典型實現

 

typedef char *va_list;

#define va_dcl int va_alist; 

#define va_start(list) l list=(char *)&va_alist

#define va_end(list) 

#define va_arg(list,mode) ((mode*)(list+=sizeof(mode)))[-1]  //可以看到這裏限制後面的參數是順序存取。

 

所以上面error被擴展爲

 

typedef char* va_list

void error(va_alist) int va_alist  /*表面看來,僅僅是一個整型參數*/

 

這個例子的假定:底層的c語言實現要求函數參數在內存中連續存儲,這樣我們只需知道當前參數的地址,就能依次訪問參數列表中的其他參數。

因此,vararg.h的這個實現中,va_list就只是一個簡單的字符指針。宏va_start把它的參數設置爲va_alist的地址,並進行了類型轉換,而宏

va_end 則什麼也不做。

 

回到??的地方,我們看到這組宏定義,並沒有標識給定的參數數目,所以使用varargs系列宏的每個程序,都有責任通過確立某種約定或慣例來標誌參數列表的結束。而printf函數使用格式字符串作爲第一個參數,通過它來識別參數數目與類型。

 

例子:使用vprintf函數來實現printf,前者直接使用va_list類型參數。

 

#include<varargs.h>

 

int printf(va_alist) va_dcl

{

      va_list ap;

      char* format;

      int n;

 

      va_start(ap);//ap指向va_alist參數列表

      format=va_arg(ap,char*);//獲取char* 類型參數,同時更新ap指向下一個參數起始位置。

      n=vprintf(format,ap);

      va_end(ap);  //不同實現,可能要求釋放內存。

     return n;

 

}

 

 

二、ANSI的varargs.h 

ANSI提供了一組新的標準來實現可變參數功能。

 

具有可變參數列表的函數,他們的第一個參數的類型在每次調用時實際上都是不變的。類似printf這樣的函數,可以通過檢查它的第一個參數,來確定它的第2個參數的類型。但是,從參數列表中我們不能確定第一個參數的類型。

使用stdarg.h的函數至少有一個固定類型的參數,後面可以跟一組未知數目,位置類型的參數。

stdarg.h文件中沒有va_arg和va_dcl宏,使用stdarg.h的函數直接聲明其固定參數,把最後一個固定定參數作爲va_sart宏的參數,來訪問可變參數。

 

 

列子:

#include <stdarg,h.

 

int printf ( char * format,..)

{

      va_list ap;

      int n;

 

      va_start(ap,format);//多了一個format,ap 指向後續可變參數

      n=vprintf(format,ap);

      va_end(ap);

      return n;

}

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章