#include<stdlib.h> #include<stdio.h> #include<stdarg.h> /* 1. 使用va_list va_start va_arg va_end实现可变参数 */ 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. 固定参数函数 */ void fixed_args_func(char x, int a, double b, char *c) { //打印参数在栈中的地址 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. 实现自己的可变参数,实则是按顺序从栈中取出参数的值 */ 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 中提供的标准可变参数宏 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的实现,va_list似乎就是char*, va_start似乎就是((char*)&fmt) + sizeof(fmt),va_arg似乎就是得到下一个参数的首地址。没错,多数平台下stdarg.h中va_list, va_start和var_arg的实现就是类似这样的。一般stdarg.h会包含很多宏,看起来比较复杂。在有的系统中stdarg.h的实现依赖some special functions built into thethe compilation system to handle variable argument lists and stack allocations,多数其他系统的实现与下面很相似:(Visual C++ 6.0的实现较为清晰,因为windows上的应用程序只需要在windows平台间做移植即可,没有必要考虑太多的平台情况)。
output://
first:4
second : 5
& int_ap = 0x003EF968
& c_ptr = 0x003EF968
& str = 0x013780D4
third1 : helloworld
third2 : helloworld
--------------------------------------
4
5.400000
helloworld
原文地址:http://xwandrew.blog.51cto.com/2909336/1974600