printf 動態參數的實現

可變參數詳解及Printf 實現方法
 
看到dbg_print(char *fmt,...) 這個函數,看了函數體,發現它實現了我從前一直疑惑的一個問題,Printf的格式化輸出是怎麼實現的,查了一些關於可變參數函數的資料,並把mtk中 printf格式化字符串的實現方式附上,但願對你們有用:  1.要在函數中使用參數,首先要包含頭文件<stdarg.h>。這個頭文件聲明瞭一個va_list類型,定義了四個宏,用來遍歷可變參數列表。 void va_start(va_list ap, last); type va_arg(va_list ap, type); void va_end(va_list ap); void va_copy(va_list dest, va_list src); 下面詳細介紹這些宏定義: 2.void va_start(va_list ap, last) va_start 必須第一個調用,它初始化va_list類型的變量ap,使ap指向第一個可選參數。參數 last 是可變參數列表(即函數原型中的省略號…)的前一個參數的名字,也就是最後類型已肯定的函數參數名。由於這個參數的地址將會被宏va_start用到,所 以最好不要是寄存器變量,函數,或者數組。 對於有可變長參數,可是在可變長參數前沒有任何的固定參數的函數,如int func (...)是不容許的。 這是ANSI C所要求的,變參函數在...以前至少得有一個固定參數。這個參 數將被傳遞給va_start(),而後用va_arg()和va_end()來肯定全部實際調用時可變長參數的類型和值。 type va_arg(va_list ap, type) 宏va_arg展開後是關於下一個參數的類型和值的表達式,參數type是明確的類型名。 va_arg返回參數列表中的當前參數並使ap指向參數列表中的下一個參數。 void va_end(va_list ap) 每次調用va_start就必須相應的調用va_end銷燬變量ap,即將指針ap置爲NULL。 void va_copy(va_list dest, va_list src) 複製va_list類型的變量。 每次調用va_copy,也必須有相應的va_end調用。 調用者在實際調用參數個數可變的函數時,要經過必定的方法指明實際參數的個數,例如把最後一個參數置爲空字符串(系統調用execl()就是這樣的)、-1或其餘的方式(函數 printf()就是經過第一個參數,即輸出格式的定義來肯定實際參數的個數的)。 3. 舉例: #include <iostream.h> #include <stdarg.h> int main() {int a,b,c,d,e; int max(int,int...); cin>>a>>b>>c>>d>>e; cout<<"The bigger between a and b is "<<max(2,a,b)<<endl; cout<<"The bigger in the five number is "<<max(5,a,b,c,d,e)<<endl; return 0; } int max(int num,int integer...) { va_list ap; int m=integer; va_start(ap,integer); for(int i=1;i<num;i++) { int t=va_arg(ap,int); if (t>m) m=t; cout<<i<<endl; } va_end(ap); return m; } 附:MTK中dbg_print函數的實現: void dbg_print(char *fmt,...) { va_list ap; double dval; int ival; char *p, *sval; char *bp, cval; int fract; unsigned short len; char buffer[1000]; memset(buffer,0,1000); bp= buffer; *bp= 0; va_start (ap, fmt); for (p= fmt; *p; p++) { if (*p != '%') { *bp++= *p; continue; } switch (*++p) { case 'd': ival= va_arg(ap, int); if (ival < 0){ *bp++= '-'; ival= -ival; } itoa (&bp, ival, 10); break; case 'o': ival= va_arg(ap, int); if (ival < 0){ *bp++= '-'; ival= -ival; } *bp++= '0'; itoa (&bp, ival, 8); break; case 'x': ival= va_arg(ap, int); if (ival < 0){ *bp++= '-'; ival= -ival; } *bp++= '0'; *bp++= 'x'; itoa (&bp, ival, 16); break; case 'c': cval= va_arg(ap, int); *bp++= cval; break; case 'f': dval= va_arg(ap, double); if (dval < 0){ *bp++= '-'; dval= -dval; } if (dval >= 1.0) itoa (&bp, (int)dval, 10); else *bp++= '0'; *bp++= '.'; fract= (int)(dval- (double)(int)dval); itof(&bp, fract); break; case 's': for (sval = va_arg(ap, char *) ; *sval ; sval++ ) *bp++= *sval; break; } } *bp= 0; // printf(buffer);這裏已經獲得了咱們想要輸出的整個字符串的內容 va_end (ap); }
相關文章
相關標籤/搜索