va_arg,va_start,va_end 使用学习
来源:互联网 发布:上瘾网络剧网盘 编辑:程序博客网 时间:2024/06/05 22:57
对于 可变参数的使用,脚本语言python,ruby使用起来很方便 不过C、C++也有利器,那就是va_arg之类函数。
笔者每次使用的时候,都要查msdn的文档, 所以这次把它记录下来。 方便以后的查询。
首先是对可变参数处理的函数有哪些,需要哪些头文件。
其次, 各个函数分别是干什么的
void test(int i,....){ va_list vPtr; //申明一个可变的变量 var_start(vPtr,i); //将 vPtr指向可变变量的第一个变量 int n = va_arg(vPtr,int);//获得当时vPtr位置的变量,并将vPtr批向下一个位置。 这里下一个位置是由va_arg的第二个参数决定的。 va_end(vPtr);//在所有的变量处理完之后,将vPtr重置为NULL}
从这个函数的实现可以看到,我们使用可变参数应该有以下步骤:
1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变
量是指向参数的指针.
2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第
一个可变参数的前一个参数,是一个固定的参数.
3)然后用va_arg返回可变的参数,并赋值给整数j. va_arg的第二个
参数是你要返回的参数的类型,这里是int型.
4)最后用va_end宏结束可变参数的获取.然后你就可以在函数里使
用第二个参数了.如果函数有多个可变参数的,依次调用va_arg获
取各个参数.
再次, 我们来看看可变参数在编译器中的处理
va_start, va_arg 和va_end是在stdarg.h中定义的, 由于硬件平台的不同与编译器的不同,所以定义的宏也有所不同,
以下,笔者会以VS2005中的定义为例。
在stdarg.h中,实际上再次引用vadefs.h中对他们的定义。
在vadef.h中, 对他们的定义如下
typedef char * va_list;#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )#define ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )#define _crt_va_end(ap) ( ap = (va_list)0 )
定义_INITSIZEOF(n)主要是为了某些为了需要内在的对齐的系统。
函数是从右向左压栈的, 下图画出了函数的参数在堆栈中的位置。
我们看到ADDRESSOF(v)是把v强制转换为char
_crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) 是获得当前固定参数的位置再加上参数所占的大小, 就指向了第一个可变变量的位置。
然后就是用va_arg来取得这个参数。
_crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
最后是va_end, _crt_va_end(ap) ( ap = (char *)0 )这样使得ap不再指向堆栈.
最后,
由于是定义的宏, 所以 可变参数的个数, 参数的类型完全是由使用者来定义的, 它并不能智能的识别不同的参数的个数与类型。
所以笔者在使用的过程中, 是模仿printf来写的, 就是在前面指定format的类型。 再用相应的类型来解析。
case 's': va_arg(arg, const char*); break;case 'i': va_arg(arg, int); break;case 't': va_arg(arg, time_t); break;case 'D': &va_arg(arg, time_t); break;case 'T': va_arg(arg, time_t); break;case 'f': va_arg(arg, double); break;
- va_arg,va_start,va_end 使用学习
- va_start、va_arg、va_end使用详解
- va_list、va_start、va_arg、va_end宏的学习
- va_start, va_arg, va_end 宏的学习
- va_start va_arg va_end 的使用和原理
- 宏:va_list、va_start、va_arg、va_end的使用
- va_start/va_arg/va_end原理与使用
- va_start/va_arg/va_end原理与使用
- va_start/va_arg/va_end原理与使用
- 宏:va_list、va_start、va_arg、va_end的使用
- va_start、va_end、va_list、va_arg的使用整理
- va_start va_arg va_end 的使用和原理
- va_start va_arg va_end 的使用和原理
- va_list、va_start、va_arg、va_end宏的使用
- va_start va_arg va_end 的使用和原理
- va_list va_start va_arg va_end原理与使用
- va_list、va_start、va_arg、va_end的使用
- va_start、va_arg、va_end、va_list的使用
- MKMapView使用的一些技巧
- zoj 2172 Symmetric Order水题
- 动态链接库内检测自己dll文件存放目录的方法
- 设计模式observer在ajax中的一个应用,解决页面onload函数同一时间只有一个可以用
- 设置listview
- va_arg,va_start,va_end 使用学习
- Android Intent调用 Uri的使用几种格式
- clearcase中一些常用的命令
- J2SE的学习重点
- 【观点】代码审查:大家都应该做的事情
- 系统host文件的使用
- J2SE(TM) 5.0专题 之 语言特性 (完整版)
- 团购之中国特色
- 移动设备的文本阅读相关的文本处理