- 1、本文档共3页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
va_list 详解
VA_LIST 是在C 语言中解决变参问题的一组宏
他有这么几个成员:
1) va_list型变量:
#ifdef _M_ALPHA
typedefstruct{
char*a0; /* pointertofirst homed integerargument*/
int offset; /* byteoffsetof next parameter */
} va_list;
#else
typedefchar* va_list;
#endif
2)_INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:
#define_INTSIZEOF(n) ((sizeof(n) + sizeof(int)- 1) ~(sizeof(int) -1) )
高地址 ||
|函数返回地址|
||
|| --va_arg后ap指向
|第n个参数(第一个可变参数) |
||--va_start后ap指向
|第n-1个参数(最后一个固定参数) |
低地址||--v
3)VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,
v是可变参数最左边的参数):
#defineva_start(ap,v) ( ap= (va_list)v + _INTSIZEOF(v))
4)VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数
描述了当前参数的类型):
#defineva_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) -_INTSIZEOF(t)))
5)VA_END 宏,清空va_list可变参数列表:
#defineva_end(ap) (ap = (va_list)0)
VA_LIST的用法:
(1)首先在函数里定义一具VA_LIST 型的变量,这个变量是指向参数的指针;
(2)然后用VA_START宏初始化变量刚定义的VA_LIST 变量,使其指向第一个可
变参数的地址;
(3)然后用VA_ARG返回可变的参数,VA_ARG 的第二个参数是你要返回的参数
的类型(如果函数有多个可变参数的,依次调用VA_ARG 获取各个参数);
(4)最后用VA_END 宏结束可变参数的获取。
使用VA_LIST应该注意的问题:
(1)可变参数的类型和个数完全由程序代码控制,它并不能智能地识别不同参数的个数
和类型;
(2)如果我们不需要一一详解每个参数,只需要将可变列表拷贝至某个缓冲,可用
vsprintf函数;
(3)因为编译器对可变参数的函数的原型检查不够严格,对编程查错不利.不利于我们写
出高质量的代码;
小结:可变参数的函数原理其实很简单,而VA系列是以宏定义来定义的,实现跟堆栈相关。
我们写一个可变参数的C 函数时,有利也有弊,所 以在不必要的场合,我们无需用到可变参
数,如果在C++里,我们应该利用C++多态性来实现可变参数的功能,尽量避免用C 语言
的方式来实现。
举例:
#includestdio.h
#includestdarg.h
/* calculatesum ofa 0 terminated list */
void sum(char* msg, ...);
Int main(int argc,char* argv[])
{
sum(Thetotalis %d\n, 1, 2,3, 4,5, 0);
return0;
}
void sum(char* msg, ...)
{
int total= 0;
int arg;
va_list ap;
va_start(ap,msg); /* ap指向第一个可变参数*/
while ((arg= va_arg(ap,int))!= 0)
{
total+= arg;
}
printf(msg, total);
va_end(ap);
}
文档评论(0)