#include#include #include /* 1. 使用va_list va_start va_arg va_end實現(xiàn)可變參數(shù) */ void simple_va_fun(int i, ...) { va_list arguments; int j = 0; int k, m; va_start(arguments, i); j = va_arg(arguments, int); m = va_arg(arguments, int); va_end(arguments); printf("%d,%d,%d\n",i,j,m); } /* 2. 固定參數(shù)函數(shù) */ void fixed_args_func(char x, int a, double b, char *c) { //打印參數(shù)在棧中的地址 printf("x = 0x%p\n", &x); printf("a = 0x%p\n", &a); printf("b = 0x%p\n", &b); printf("c = 0x%p\n", &c); } /* 3. 實現(xiàn)自己的可變參數(shù),實則是按順序從棧中取出參數(shù)的值 */ void var_args_func(const char * fmt, ...) { char* ap; ap = (char *)&fmt + sizeof(fmt); int* int_ap = (int *)ap; printf("first:%d\n",*int_ap); int_ap = int_ap + 1; printf("second:%d\n",*int_ap); int_ap = int_ap + 1;// string start index char* c_ptr = (char*)int_ap; char* str = (char* )*int_ap; printf("&int_ap = 0x%p\n",int_ap); printf("&c_ptr = 0x%p\n", c_ptr); printf("&str = 0x%p\n",str); //棧里面存儲的是指向字符串"helloworld的指針",即二級字符指針 printf("third1: %s\n",str); printf("third2: %s\n", *(char **)int_ap); } //stdarg.h 中提供的標準可變參數(shù)宏 void std_vararg_func(const char *fmt, ...) { va_list ap; va_start(ap, fmt); printf("%d\n", va_arg(ap, int)); printf("%f\n", va_arg(ap, double)); printf("%s\n", va_arg(ap, char*)); va_end(ap); } int main() { //fixed_args_func('a',17, 5.40, "hello world"); //char* p = "xiongwei"; //printf("%d\n",sizeof(p)); var_args_func("%d %d %s\n", 4, 5, "helloworld"); printf("--------------------------------------\n"); std_vararg_func("%d %f %s\n", 4, 5.4, "helloworld"); system("pause"); return 0; }
對比一下 std_vararg_func和var_args_func的實現(xiàn),va_list似乎就是char*, va_start似乎就是((char*)&fmt) + sizeof(fmt),va_arg似乎就是得到下一個參數(shù)的首地址。沒錯,多數(shù)平臺下stdarg.h中va_list, va_start和var_arg的實現(xiàn)就是類似這樣的。一般stdarg.h會包含很多宏,看起來比較復雜。在有的系統(tǒng)中stdarg.h的實現(xiàn)依賴some special functions built into thethe compilation system to handle variable argument lists and stack allocations,多數(shù)其他系統(tǒng)的實現(xiàn)與下面很相似:(Visual C++ 6.0的實現(xiàn)較為清晰,因為windows上的應用程序只需要在windows平臺間做移植即可,沒有必要考慮太多的平臺情況)。
成都網(wǎng)絡公司-成都網(wǎng)站建設公司成都創(chuàng)新互聯(lián)公司十多年經(jīng)驗成就非凡,專業(yè)從事成都做網(wǎng)站、網(wǎng)站建設,成都網(wǎng)頁設計,成都網(wǎng)頁制作,軟文發(fā)布平臺,1元廣告等。十多年來已成功提供全面的成都網(wǎng)站建設方案,打造行業(yè)特色的成都網(wǎng)站建設案例,建站熱線:028-86922220,我們期待您的來電!
output://
first:4
second : 5
& int_ap = 0x003EF968
& c_ptr = 0x003EF968
& str = 0x013780D4
third1 : helloworld
third2 : helloworld
--------------------------------------
4
5.400000
helloworld
實現(xiàn)Printf()函數(shù):
#include "stdio.h" #include "stdlib.h" void myprintf( char* fmt, ... ) /* 一個簡單的類似于printf的實現(xiàn),//參數(shù)必須都是int 類型 */ { char * pArg = NULL; /* 等價于原來的va_list */ char c; pArg = (char *) &fmt; /* 注意不要寫成p = fmt !!因為這里要對//參數(shù)取址,而不是取值 */ pArg += sizeof(fmt); /* 等價于原來的va_start */ do { c = *fmt; if ( c != '%' ) { putchar( c ); /* 照原樣輸出字符 */ }else { /*按格式字符輸出數(shù)據(jù) */ switch ( *++fmt ) { case 'd': printf( "%d", *( (int *) pArg) ); break; case 'x': printf( "%#x", *( (int *) pArg) ); break; default: break; } pArg += sizeof(int); /* 等價于原來的va_arg */ } ++fmt; } while ( *fmt != '\0' ); pArg = NULL; /* 等價于va_end */ return; } int main( int argc, char* argv[] ) { int i = 1234; int j = 5678; myprintf( "thefirst test:i=%d", i, j ); myprintf( "thesecend test:i=%d; %x;j=%d;", i, 0xabcd, j ); system( "pause" ); return(0); }