va_list,va_start,va_arg,va_end可变参数
来源:互联网 发布:74157数据选择器 编辑:程序博客网 时间:2024/04/28 02:49
va_list,va_start,va_end定义在c库的stdarg.h头文件中
大致定义如下,不同标准的定义不全一样
typedef char* va_list;#define __va_argsiz(t) (((sizeof(t) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))#define va_start(ap, pN) ((ap) = ((va_list)(&pN) + __va_argsiz(pN)))#define va_arg(ap, t) (((ap) = (ap) + __va_argsiz(t)), *((t*) (void*) ((ap) - __va_argsiz(t))))#define va_end(ap) ( ap = (va_list)0 )
__va_argsiz(t)的作用,计算参数占用的机器字长
int 的长度与机器字长相同, 16位的编译器上int长16位,32位的编译器上int长32位...
以32位机为例
char占用一个8位的内存单元
int占用4个8位的内存单元
例子分析固定参数和可变参数的内存布局
//以32位机器为例char *e="hello";int i=0x12345678;printf("i=%d e=%s",i,e);
参数的内存对齐方式,不考虑大小端.
va_list,va_start,va_arg,va_end的
典型的应用例子
#include <stdarg.h>#define MAXARGS 31/* * execl is called by * execl(file, arg1, arg2, ..., (char *)(0)); */int execl(const char *file, const char *args, ...){ va_list ap;//定义参数链表 char *array[MAXARGS +1]; int argno = 0; va_start(ap, args);//获取第一个可变参数 while (args != 0 && argno < MAXARGS) { array[argno++] = args; args = va_arg(ap, const char *);//获取下一个可变参数 } array[argno] = (char *) 0; va_end(ap);//释放指针 return execv(file, array);}
解析1
int execl(const char *file, const char *args, ...){ char* ap; char *array[MAXARGS +1]; int argno = 0;(ap) = ((char*)(&args) + __va_argsiz(args)) while (args != 0 && argno < MAXARGS) { array[argno++] = args;args = (((ap) = (ap) + __va_argsiz(const char *)), *((const char **) (void*) ((ap) - __va_argsiz(const char *)))) } array[argno] = (char *) 0; ap=(char*)0; return execv(file, array);}
这里运用到了逗号运算符
A=(b,c,d)等价于运算完b,c,d表达式后令A=d
进一步解析
解析2
int execl(const char *file, const char *args, (char *)varg1,(char *)varg2,....){ char* ap; char *array[MAXARGS +1]; int argno = 0;(ap) = ((char*)(&args) + __va_argsiz(args))//指向固定参数+固定参数大小==指向第一个可变参数 while (args != 0 && argno < MAXARGS) {array[argno++] = args;//填充字串数组(ap) = (ap) + __va_argsiz(const char *)//ap指下一个可变参数args = *((const char **) (void*) ((ap) - __va_argsiz(const char *))) } array[argno] = (char *) 0; ap=(char*)0;//释放ap指针 return execv(file, array);}
(ap) = ((char*)(&args) + __va_argsiz(args))这里ap指向args的地址+args占用的内存大小,所以ap指向了varg1
进入while循环,进入条件,参数非空,参数个数未超出MAXARGS
array[argno++] = args; -->arry[0]=args 第二次循环array[1]=varg1,第三次循环array[2]=varg2....
(ap) = (ap) + __va_argsiz(const char *)---------->ap指向下一个(const char*)可变参数
args = *((const char **) (void*) ((ap) - __va_argsiz(const char *)))指向本次操作的可变参数,
因为前面(ap) = (ap) + __va_argsiz(const char *)操作,所以其实args实际上等于
args = *((const char **) (void*) ((ap) + __va_argsiz(const char *) - __va_argsiz(const char *)))
化简得
args = *((const char **) (void*) (ap)
接着回到while语句,继续处理下一个可变参数
用法框架:
xxx func(,const char *args,varg1,varg2,...){va_list ap;//定义参数链表va_start(ap, args);//获取第一个可变参数循环{处理处理可变参数va_arg(ap,可变参数类型)//获取下一个可变参数}va_end(ap);//释放指针return xxx;}
- va_list,va_start,va_arg,va_end可变参数
- 函数可变参数va_list、va_start、va_arg、va_end原理及使用方法
- 可变参数列表(va_list,va_arg,va_copy,va_start,va_end)
- 可变参数列表的函数调用 va_list va_start va_arg va_end
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- C语言中的可变参数:va_list ,va_start,va_arg,va_end
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- 可变参数列表(va_list,va_arg,va_copy,va_start,va_end)
- C语言可变参数,va_arg、va_list,va_start,va_end,_INTSIZEOF
- 可变参数列表(va_list,va_arg,va_copy,va_start,va_end)
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- 函数可变参数深入分析之va_list、va_start、va_arg、va_end
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- 可变参数列表(va_list,va_arg,va_copy,va_start,va_end)
- 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)
- C语言可变参数--va_list、va_start、va_arg、va_end
- 深入C语言可变参数(va_arg,va_list,va_start,va_end)
- Ubuntu12.10 双显卡过热问题
- MFC基础-----消息机制基础
- Ubuntu 12.04 ATI/Intel双显卡 驱动安装
- poj 2965
- IKAnalyzer分词
- va_list,va_start,va_arg,va_end可变参数
- .NET中资料库的设计与SQL
- 【javascript】JS中获取系统时间
- 简单01背包问题求解 POJ:3628 Bookshelf 2
- c++模板之声明定义分离编译模型
- PPTV
- 什么是git rebase
- 不想用MFC,涂鸦一个主窗口框架类吧
- 年轻人,心理素质!