对CC++可变参数表的深层探索

对CC++可变参数表的深层探索,第1张

对CC++可变参数表的深层探索,第2张

介绍

C/C++语言不同于其他语言,它支持可变参数。printf和scanf等典型函数可以接受数量不定的参数。比如:

printf(“我爱你”);
printf ( "%d ",a);
printf ( "%d,%d ",a,b);

第一、第二和第三个printfs分别接受1、2和3个参数。让我们来看看printf函数的原型:

int printf(const char *格式,...);

从函数的原型可以看出,除了接收固定的参数格式,下面的参数用“…”表示。在C/C++语言中,“…”意味着可以接受不确定数量的参数。理论上可以是0,也可以是0 N个以上的参数。

本文将探讨C/C++可变参数表的用法以及C/C++支持可变参数表的深层机制。

可变参数表的用法

1.相关宏

标准C/C++包含头文件stdarg.h,其中定义了以下三个宏:

void va_start ( va_list arg_ptr,prev _ param);/* ANSI版本*/
type va _ arg(va _ list arg _ ptr,type);
void va _ end(va _ list arg _ ptr);

在这些宏中,va表示变量自变量;Arg_ptr是变量参数表的指针;Prev_param引用可变参数表的前一个固定参数;Type是可变参数的类型。va_list也是一个宏,定义为typedef char * va_list,本质上是一个char指针。Char指针的特点是++ and-运算的结果增减1(因为sizeof(char)是1),这与int等其他类型指针++ and-运算的结果不同,它增减sizeof(type),sizeof(type)大于1。

我们可以通过va_start宏得到变量参数表的第一个指针,定义为:

#define va_start ( ap,v ) ( ap = (va_list)&v + _INTSIZEOF(v))

很明显,它的意思是把最后一个固定参数的地址加上可变参数的偏移量赋给ap,这样ap就是可变参数表的第一个地址。_INTSIZEOF的宏定义为:

# define _ int sizeof(n)((sizeof(n)+sizeof(int)-1)& ~(sizeof(int)-1))

va_arg宏的意思是取出当前arg_ptr指向的变量参数,将ap指针指向下一个变量参数。它的原型是:

# defineva _ arg (list,mode)((mode *)(list = \
(char *)(((int)list+(_ _ builtin _ align of(mode))(_ _ builtin _ align of(mode))这个宏的具体含义后面会讨论。

va_end宏用于结束变量参数的采集,定义为:

#定义va_end(列表)

可以看出,va_end (list)实际上定义为空,没有任何真正对应的代码,用于代码对称,对应va _ start此外,它还可能起到代码“自我注释”的作用。所谓代码的“自注释”是指代码可以对自己进行注释。

下面用具体例子来说明以上三个宏的用法。

2.简单的例子

#include
/* 函数名:max
* 功能:返回n个整数中的值
* 参数:num:整数的个数 ...:num个输入的整数
* 返回值:求得的整数
*/
int max ( int num, ... )
{
 int m = -0x7FFFFFFF; /* 32系统中最小的整数 */
 va_list ap;
 va_start ( ap, num );
 for ( int i= 0; i< num; i++ )
 {
  int t = va_arg (ap, int);
  if ( t > m )
  {
   m = t;
  }
 }
 va_end (ap);
 return m;
}
/* 主函数调用max */
int main ( int argc, char* argv[] )
{
 int n = max ( 5, 5, 6 ,3 ,8 ,5); /* 求5个整数中的值 */
 cout

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 对CC++可变参数表的深层探索

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情