void foo(int argv1, char argv2, …)
在參數列的末尾給出省略號,表明這個函式的引數是可變的
程序在呼叫函式時,會將函式引數壓入使用者棧,壓入的順序是從參數列右端開始,從右至左的壓棧順序支援了可變引數的實現。左邊的引數在低位址,右邊的引數在高位址。進入函式後,以左邊的引數為線索,可透過指標依次訪問右邊省略掉的引數。
可變引數的實現一定會涉及到三個函式和乙個變數,巨集定義在stdarg.h中
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
實現正確的函式呼叫,可遵循以下步驟:
1.定義乙個va_list型別變數,變數名為ap
2.使用函式va_start(ap, last)對ap進行初始化,第乙個引數是ap,第二個引數是省略號前乙個變數,在有多個變數的情況下需注意。
3.使用va_arg(ap, type)獲取省略號中的可變引數,該可變引數的型別應為type,並將指標指向下乙個可變引數
4.在獲取完所有的可變引數後(需要小心指標越界),用函式va_end(ap)關閉ap。
下面是glibc中函式printf()的實現原始碼
//glibc 2.14.1
/* write formatted output to stdout from the format string format. */
/* varargs1 */
int__printf (const
char *format, ...)
我們可以自己實現簡易版的myprintf()
#include
#include
//如果在嵌入式系統中,putchar(ch) 可換成串列埠輸出函式
#define console_print(ch) putchar(ch)
void myprintf(char* fmt, ...);
void printch(char ch);
void printdec(int dec);
void printflt(double flt);
void printbin(int bin);
void printhex(int hex);
void printstr(char* str);
int main(void)
void myprintf(char* fmt, ...)
pfmt++;
}else
}va_end(vp);
}void printch(char ch)
void printdec(int dec)
printdec(dec/10);
printch( (char)(dec%10 + '0'));
}void printflt(double flt)
void printstr(char* str)
}void printbin(int bin)
printbin(bin/2);
printch( (char)(bin%2 + '0'));
}void printhex(int hex)
printhex(hex/16);
if(hex < 10)
else
}
1.可變引數』…』裡面的char會被提公升為int,float會被提公升為double。如果我們將va_arg(ap, int)改為va_arg(ap, char),系統會給出乙個警告。詳情可見[3].
waring: 'char' is promoted to 'int' when passed to through '...'2.一定要使用arg_end(),可提高程式的移植性和健壯性。詳情可見[4].
【reference】
1.myprintf實現
2.stdarg相關函式
3.va_arg不可接受的型別
4.va_end是必須的嗎
printf可變引數實現
print.h cpp view plain copy print ifndef print h define print h voidprint char fmt,voidprintch charch voidprintdec intdec voidprintflt doubleflt voidp...
printf可變引數原理
當呼叫printf時引數的個數是不限定的,那麼該函式是如何實現的呢?來看一下該函式的定義 int printf const char format,argument printf的第乙個引數就是那個字元指標即為被雙引號括起來的那一部分,函式通過判斷字串裡控制引數的個數 d等等 來判斷引數個數及資料型...
printf 可變引數封裝
define fb fmt,fa fmt,va args va args 就只是告訴編譯器,fa可以接受可變引數,不要報錯,相當於又把 傳遞下去了 兩個 的解釋請參見宋寶華 linux裝置驅動程式開發詳解 4.0核心 p80 void fa fmt,typedef char va list va l...