前些天在看 晨宇思远 的一篇博文:OpenCV学习笔记(5) 在单个窗口中显示多个视频子窗口http://blog.csdn.net/chenyusiyuan/article/details/4642297 ,为了实现能够灵活调整子窗口的个数,他采用了可变参数的方式来实现。虽然这个功能实现起来不难,但是之前并没有用到过,所以这里就根据网上的一些资料稍微整理一下,以便后用。
C中实现变参主要是通过VA_LIST这一组宏来实现,它包含一下几个成员:
va_list型变量
从头文件stdarg.h中查到va_list变量的定义如下:
#ifndef _VA_LIST_DEFINED #ifdef _M_ALPHA typedef struct { char *a0; /* pointer to first homed integer argument */ int offset; /* byte offset of next parameter */ } va_list; #else typedef char * va_list; #endif #define _VA_LIST_DEFINED #endif
va_start宏
该宏定义如下:
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
该宏主要用来获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是第一个可变参数的前面一个参数,也即函数参数列表中省略号之前的一个参数)
这里涉及到另外一个宏 _INTSIZEOF ,它的定义如下:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
该宏用来获取类型n占用的空间长度,最小占用长度为int的整数倍。
va_arg宏
该宏定义如下:
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
该宏获取可变参数的当前参数,并将指针ap指向下一个可变参数(ap是类型为va_list的指针,t为可变参数的类型)
va_end宏
该宏定义如下:
#define va_end(ap) ( ap = (va_list)0 )
该宏用来清除va_list指针值
下面举一个简单的例子来说明如何实现可变参数函数,代码如下:
void simple_va_fun(int nArgs, ...) { va_list arg_ptr; //定义一个va_list类型的变量 int arg1=0, arg2=0, arg3=0; va_start(arg_ptr, nArgs); //arg_ptr指向第一个可变参数,即i后面的那个参数 if(nArgs <= 0) { printf("Number of arguments too small....\n"); return; } else if(nArgs > 3) { printf("Number of arguments too large....\n"); return; } else if(nArgs == 1) { arg1=va_arg(arg_ptr, int);//获取arg_ptr当前所指向的参数值,并将其指向下一个可变参数 printf("arg1= %d\n", arg1); } else if(nArgs == 2) { arg1=va_arg(arg_ptr, int); arg2=va_arg(arg_ptr, int); printf("arg1= %d arg2= %c\n", arg1, arg2); } else if(nArgs == 3) { arg1=va_arg(arg_ptr, int); arg2=va_arg(arg_ptr, int); arg3=va_arg(arg_ptr, int); printf("arg1= %d arg2= %d arg3= %s\n", arg1, arg2, arg3); } va_end(arg_ptr); //清除arg_ptr指针值 return; }
在主函数中以如下方式调用该函数:
simple_va_fun(1, 300); simple_va_fun(2, 300, 'c'); simple_va_fun(3, 300, 100, "test");
运行结果如下图所示:
以上这个简单的例子说明了如何实现变参函数。上面的例子只是简单的说明了参数个数不固定的情况,对于参数类型不固定的情况没有很好的实现.
参考网站:http://www.cppblog.com/xmoss/archive/2009/07/20/90680.aspx