您的位置:首页 > 其它

<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 提取地址发生错误)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: