鱼C论坛

 找回密码
 立即注册
查看: 3453|回复: 5

[技术交流] 可变参数

[复制链接]
发表于 2011-7-24 17:11:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
C/C++语言有一个不同于其它语言的特性,即其支持可变参数,典型的函数如printf、scanf等可以接受数量不定的参数。如:

printf ( "I love you" );
printf ( "%d", a );
printf ( "%d,%d", a, b );

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

int printf ( const char *format, ... );

  从函数原型可以看出,其除了接收一个固定的参数format以外,后面的参数用"…"表示。在C/C++语言中,"…"表示可以接受不定数量的参数,理论上来讲,可以是0或0以上的n个参数。

  本文将对C/C++可变参数表的使用方法及C/C++支持可变参数表的深层机理进行探索。

  可变参数表的用法

  1、相关宏

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

void va_start ( va_list arg_ptr, prev_param ); /* ANSI version */
type va_arg ( va_list arg_ptr, type );
void va_end ( va_list arg_ptr );

  在这些宏中,va就是variable argument(可变参数)的意思;arg_ptr是指向可变参数表的指针;prev_param则指可变参数表的前一个固定参数;type为可变参数的类型。va_list也是一个宏,其定义为typedef char * va_list,实质上是一char型指针。char型指针的特点是++、--操作对其作用的结果是增1和减1(因为sizeof(char)为1),与之不同的是int等其它类型指针的++、--操作对其作用的结果是增sizeof(type)或减sizeof(type),而且sizeof(type)大于1。

  通过va_start宏我们可以取得可变参数表的首指针,这个宏的定义为:

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

  显而易见,其含义为将最后那个固定参数的地址加上可变参数对其的偏移后赋值给ap,这样ap就是可变参数表的首地址。其中的_INTSIZEOF宏定义为:

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

  va_arg宏的意思则指取出当前arg_ptr所指的可变参数并将ap指针指向下一可变参数,其原型为:

#define va_arg(list, mode) ((mode *)(list =\
(char *) ((((int)list + (__builtin_alignof(mode)<=4?3:7)) &\
(__builtin_alignof(mode)<=4?-4:-8))+sizeof(mode))))[-1]

  对这个宏的具体含义我们将在后面深入讨论。

  而va_end宏被用来结束可变参数的获取,其定义为:

#define va_end ( list )

  可以看出,va_end ( list )实际上被定义为空,没有任何真实对应的代码,用于代码对称,与va_start对应;另外,它还可能发挥代码的"自注释"作用。所谓代码的"自注释",指的是代码能自己注释自己。

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

  2、一个简单的例子

#include <stdarg.h>
/* 函数名: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 << n;
 return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2011-7-24 19:39:14 | 显示全部楼层
实习版主很给力嘛  顶一个!!{:7_156:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2013-7-2 22:29:11 | 显示全部楼层
看帖就要回帖支持下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-7-2 23:38:00 | 显示全部楼层
看看,支持下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-7-3 11:38:35 | 显示全部楼层
看不懂啊。。。。。才疏学浅了么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-7-3 12:44:06 | 显示全部楼层
还没这实力看的懂哎,走的路还很长
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-4 22:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表