stdarg.h

stdarg.h是C語言中C標準函式館的頭檔案,stdarg是由standard(標準) arguments(參數)簡化而來,主要目的為讓函式能夠接收可變參數。C++的cstdarg頭檔案中也提供這樣的功能;雖然與C的頭檔案是兼容的,但是也有衝突存在。 可變參數函式(Variadic functions)是stdarg.h內容典型的套用,雖然也可以使用在其他由可變參數函式調用的函式(例如,vprintf)。

可變參數函式

聲明可變參數函式

可變參數函式的參數數量是可變動的,它使用省略號來忽略之後的參數。例如printf函式一般。代表性的聲明為:

int check(int a, double b, ...);

可變參數函式最少要有一個命名的參數,所以

char *wrong(...);

在C中是不被允許的(在C++中,這樣的聲明是合理的)。C中,省略符號之前必須要有逗號;而在C++中,則沒有這種強制要求。

定義可變參數函式

使用相同的語法來定義:

long func(char, double, int, ...);

long func(char a, double b, int c, ...)

{

/* ... */

}

在C的舊形式中可能會出現較省略的函式定義:

long func();

char a;

double b;

long func(a, b, c, ...)

{

/* ... */

}

成員

stdarg.h數據類型

類型名稱 描述 相容
va_list 用來保存宏va_arg與宏va_end所需信息 C89

stdarg.h宏

巨集名稱 描述 相容
va_start 使va_list指向起始的參數 C89
va_arg 檢索參數 C89
va_end 釋放va_list C89
va_copy 拷貝va_list的內容 C99

訪問參數

訪問未命名的參數,首先必須在可變參數函式中聲明va_list類型的變數。調用va_start並傳入兩個參數:第一個參數為va_list類型的變數,第二個為省略號前最後一個有名字的參數的名稱,接著每一調用va_arg就會返回下一個參數,va_arg的第一個參數為va_list,第二個參數為返回的類型。最後va_end必須在函式返回前被va_list調用(va_list當作參數)(沒有要求要讀取完所有參數)。

C99提供額外的宏,va_copy,它能夠複製va_list。而va_copy(va2, va1)函式作用為拷貝va1到va2。

沒有機制定義該怎么判別傳遞到函式的參數量或者數據類型。函式通常需要知道或確定它們變化的方法。共通的慣例包含:

使用printf或scanf類的格式化字串來嵌入明確指定的類型。

在可變參數最後的標記值(sentinel value)。

總數變數來指明可變參數的數量。

類型安全性

有些C實現提供了對可變參數的擴展,允許編譯器檢查適當的格式化字串及標誌(sentinels)的使用。如果沒有這個擴充,編譯器通常無從檢查傳入函式的未命名參數是否為所預期的類型。因此,必須小心謹慎以確保正確性,因為不匹配的數據類型將導致未定義行為(Undefined behavior)。例如,如果傳遞空指針,不能僅僅寫入NULL(可能實際定義為0),還要轉化為適當的指針類型。另一個考慮是未命名參數的默認的類型提升。float將會自動的被轉換成double。同樣的,比int(整數)更小容量的參數數據類型將會被轉換成int或者unsigned int。函式所接收到的未命名參數必須提前考慮將會出現的數據類型提升。

舉例

#include <stdio.h>

#include <stdarg.h>

void printargs(int arg1, ...) /* 輸出所有int類型的參數,直到-1結束 */

{

va_list ap;

int i;

va_start(ap, arg1);

for (i = arg1; i != -1; i = va_arg(ap, int))

printf("%d ", i);

va_end(ap);

putchar('\n');

}

int main(void)

{

printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);

printargs(84, 51, -1);

printargs(-1);

printargs(1, -1);

return 0;

}

這個程式產生輸出:

5 2 14 84 97 15 24 48

84 51

1

頭檔案

POSIX定義所遺留下的頭檔案varargs.h,它早在C標準化前就已經開始使用了且提供類似stdarg.h的功能。MSDN明確指出這一頭檔案已經過時,完全被stdarg.h取代。這個頭檔案不屬於ISO C的一部分。檔案定義在單一UNIX規範的第二個版本中。

由於varargs.h不屬於標準C,所以不對其詳細說明。

熱門詞條

聯絡我們