<cstdarg>头文件
2012-07-20 14:37
369 查看
宏与类型定义
_INTSIZEOF宏
宏定义:// vadefs.h #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
_ADDRESSOF
宏定义:// vadefs.h #define _ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )
va_start宏
宏定义:// stdarg.h #define va_start _crt_va_start // vadefs.h #define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
作用: 使 va_list 指向起始的参数
参数:
ap 为 va_list 类型的变量
v 函数的第一个固定参数
va_arg宏
宏定义:// stdarg.h #define va_arg _crt_va_arg // vadefs.h #define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
作用: 检索参数,每次提取一次可变参数,arg 就向上移动一次.无论它现在指向的是不是参数它都会读取arg参数里存放地址里的内容
参数:
ap 为 va_list 类型的变量
t 为回传的型态
va_end宏
宏定义:// stdarg.h #define va_end _crt_va_end // vadefs.h #define _crt_va_end(ap) ( ap = (va_list)0 )
作用: 释放 va_list
参数: ap 为 va_list 类型的变量
va_list类型
定义:// stdarg.h typedef char * va_list;
对于函数
形式:type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
void va_start( va_list arg_ptr ); (UNIX version)
void va_start( va_list arg_ptr, prev_param ); (ANSI version)
参数解释:
type: Type of argument to be retrieved
arg_ptr: Pointer to list of arguments
prev_param: Parameter
使用可变参数
使用可变参数的下步骤首先在函数里定义一个 va_list 型的变量,这里是 arg_ptr,这个变量是指向参数的指针.
然后用 va_start 宏初始化变量 arg_ptr,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数.
然后用 va_arg 返回可变的参数,并赋值给整数 j. va_arg的第二个 参数是你要返回的参数 的类型,这里是 int 型.
最后用 va_end 宏结束可变参数的获取.然后你就可以在函数里使用第二个参数了.如果函数有多个可变参数的,依次调用 va_arg 获取各个参数
C 语言的函数是从右向左压入堆栈的,下图是函数的参数在堆栈中的分布位置:
例子
输出所有int型态的参数,直到-1结束:#include<iostream> #include <cstdarg> using namespace std; void printargs(int arg1,...) { va_list ap; //声明变量 ap,用于指向参数 int i; va_start(ap,arg1); //获得第一个参数的地址 //va_start(ap,arg1); 把宏展开来看等价于 //(ap =(char*)(&reinterpret_cast<const char&>(arg1))+((sizeof(arg1)+sizeof(int)-1)&~(sizeof(int)- 1))); for(i=arg1;i!=-1;i=va_arg(ap,int)) //va_arg(ap,int) 把宏展开来看等价于 //(*(int*)((ap +=((sizeof(int)+sizeof(int)- 1)&~(sizeof(int)- 1)))-((sizeof(int)+sizeof(int)- 1) &~(sizeof(int)- 1)))) //输出所有int型态的参数,直到-1结束 cout<<i<<' '; va_end(ap); //va_end(ap); 把宏展开来看等价于 //(ap =(char*)0) cout<<endl; } int main(void) { printargs(5,2,14,84,97,15,24,48,-1); printargs(84,51,-1); printargs(-1); printargs(1,-1); system("pause"); return 0; }
输出结果:
5 2 14 84 97 15 24 48
84 51
1
请按任意键继续. . .
用可变参数第一参数为参数的长度说明:
#include<iostream> #include <cstdarg> using namespace std; void output(int n, ...); void main() { output(3,"王一",12,"李二",5,"赵三",58); system("pause"); } void output(int n, ...) { va_list ap; va_start(ap,n); //起到初始化,使用得 ap 指向可变参数的第一个参数,即 n 处 while(n--) { char* name=va_arg(ap,char*); //获得当前 ap 所指向的参数,并使 ap 指向可变参数的下一个参数,并且要指明获得的参数类型char* 为需要获得的参数的类型. int age=va_arg(ap,int); //同上,int为参数类型 cout<<"name :"<<name<<",age="<<age<<endl; } va_end(ap); //结束可变参数获取 }
输出结果:
name :王一,age=12
name :李二,age=5
name :赵三,age=58
请按任意键继续. . .
若把上例子中的函数调用由 output(3,"王一",12,"李二",5,"赵三",58); 改为output(3,"王一",12,"李二",5); 时候输出结果变成了这样(在参数后面还有跟着一些函数的相关信息):
name :王一,age=12
name :李二,age=5
name :兡 ?0@,age=1
请按任意键继续. . .
若把上例子中的函数调用由 output(3,"王一",12,"李二",5,"赵三",58); 改为output(3,"王一",12,"李二"); 时候输出结果变成了这样(错误说明:读取的地址无效,.va_arg 提取地址发生错误):
若把上例子中的函数调用由 output(3,"王一",12,"李二",5,"赵三",58); 改为output(3,"王一",12); 时候输出结果变成了这样(在参数后面还有跟着一些函数的相关信息):
name :王一,age=12
name :兡 ?0@,age=1
name :萐;,age=3880944
请按任意键继续. . .
若把上例子中的函数调用由 output(3,"王一",12,"李二",5,"赵三",58); 改为output(3); 时候输出结果变成了这样(
错误说明:读取的地址无效.va_arg 提取地址发生错误):
若把上例子中的函数调用由 output(3,"王一",12,"李二",5,"赵三",58); 改为output(n); 并且 n>3 时候输出结果和上面一样( 错误说明:读取的地址无效.va_arg 提取地址发生错误)
相关文章推荐
- <PY><core python programming笔记>C9 文件和输入输出
- 只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态。还请确保在应用程序配置的 <configuration>
- <转>C语言中的文件输入输出函数
- C++中头文件使用""与<>的区别
- <<Python基础教程>>学习笔记 | 第11章 | 文件和素材
- Java中的 File类对文件 路径分割符不敏感! <发现>
- <string>头文件
- <转载>在Linux下文件的三种时间标记:访问时间、修改时间、状态改动时间
- <转>用已经存在的xml文件作为flex柱状图饼状图等数据源的方式有几种?
- <SVN>使用SVN小乌龟对比单个文件任意版本的差异
- <PY>PYTHON读取大文本文件时的注意事项
- <转>BufferedReader和FileReader读取txt文件乱码
- &lt;转&gt;&nbsp;iOS开发网络篇—大文件的…
- <<我的 .gitignore 文件>>
- struts2文件下载 <result type="stream">
- JAVA IO流 <一>文件基本操作
- <Feb 28, 2015 3:21:18 PM CST> <Info> <Management> <BEA-141281> <unable to get file lock, will retry
- <Eclipse+Android>import已经导入的文件提示已存在
- <input type="file" />浏览时只显示指定文件类型
- <input >上传图片文件的解说