例如可變參函數(shù)printf的函數(shù)原型/函數(shù)聲明為:int printf(char *fmt, ...);
其中參數(shù)表必須至少包括一個(gè)有名參數(shù)(如fmt);省略號(hào)表示參數(shù)表中參數(shù)的數(shù)量和類型是可變的,且省略號(hào)只能出現(xiàn)在參數(shù)表的尾部。
在標(biāo)準(zhǔn)頭文件<stdarg.h>
中包含一組宏定義膛堤,它們對(duì)如何遍歷未知數(shù)目和類型的函數(shù)參數(shù)表進(jìn)行了定義;該頭文件的實(shí)現(xiàn)因不同的機(jī)器而不同柠并,但提供的接口是一致的澜公。主要的宏如下:
void va_start(va_list ap,lastarg);
type va_arg(va_list ap,type);
void va_end(va_list ap);
- va_list: va_list類型用于聲明一個(gè)變量ap,該變量將依次引用變長(zhǎng)參數(shù)列表中各參數(shù)萍歉,定義為
typedef char *va_list
侣颂。 - va_start:宏va_start將ap初始化為指向第一個(gè)無(wú)名參數(shù);lastarg為最后一個(gè)有名參數(shù)枪孩。
- va_arg:va_arg將返回ap指向的參數(shù)憔晒,并將ap指向下一個(gè)參數(shù);va_arg使用一個(gè)類型名(type)來(lái)決定返回的對(duì)象類型蔑舞、ap移動(dòng)的步長(zhǎng)拒担。
- va_end:最后必須在函數(shù)返回前調(diào)用va_end,以完成一些必要的清理工作攻询。(va:variable argument)
- 在沒(méi)有函數(shù)原型的情況下从撼,char與short類型都將轉(zhuǎn)換為int類型;float類型將被轉(zhuǎn)換為double類型钧栖。實(shí)際上低零,用
...
標(biāo)識(shí)的可變參總是會(huì)執(zhí)行這種類型提升(Type Promotions)。
一個(gè)簡(jiǎn)單可變參數(shù)函數(shù):
#include<stdio.h>
#include<stdarg.h>
void f(char *fmt, ...);
int main(void)
{
printf("f is a variable argument function \n");
f("%s,%s,%s,%s,%s,%s","f","is","a","variable","argument","function");
return 0;
}
void f(char *fmt, ...)
{
va_list ap; /*聲明一個(gè)引用變長(zhǎng)參數(shù)的變量*/
va_start(ap,fmt); /*將ap初始化為指向第一個(gè)無(wú)名參數(shù)*/
int i=1;
char *p=fmt;
while(*p){
if('%'==*p && 's'==*(p+1))
printf("%s is #%d parameter\n",va_arg(ap,char *),++i); /*va_arg將返回ap指向的參數(shù)拯杠,并將ap指向下一個(gè)參數(shù)*/
p++;
}
va_end(ap); /*函數(shù)返回前調(diào)用va_end*/
}