複製鏈接
請複製以下鏈接發送給好友

stdarg.h

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

stdarg.h可變參數函數

聲明可變參數函數
可變參數函數的參數數量是可變動的,它使用省略號來忽略之後的參數。例如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成員

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

stdarg.h訪問參數

訪問未命名的參數,首先必須在可變參數函數中聲明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)。
總數變量來指明可變參數的數量。

stdarg.h類型安全性

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

stdarg.h舉例

#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

stdarg.h頭文件

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