[C++基础]040_可变参数va_list的一段示例代码
1 #include <stdio.h> 2 #include <stdarg.h> 3 4 void WriteFormatted (FILE * stream, const char * format, ...) 5 { 6 va_list args; 7 va_start (args, format); 8 vfprintf (stream, format, args); 9 va_end (args); 10 } 11 12 int main () 13 { 14 FILE * pFile; 15 16 pFile = fopen ("myfile.txt","w"); 17 18 WriteFormatted (pFile,"Call with %d variable argument.\n",1); 19 WriteFormatted (pFile,"Call with %d variable %s.\n",2,"arguments"); 20 21 fclose (pFile); 22 getchar(); 23 return 0; 24 }
va_list的实现原理,这里简单的介绍一下:
在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减.
总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段.堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.
而上面用到的几个看似函数的函数,其实是宏,它们的作用就是获取函数的参数列表的地址,它们的定义如下:
1 #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) 2 #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址 3 #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址 4 #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效