已阅读:3,776 次
C++不定参数的实现
ian | C/C++ | 2011/03/12


说到不定参数,我们最先想到的就是C++里经常用到printf函数,这个函数可以接收不定数量的参数,函数原型如下:

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

这里第一个参数后的“…”表示该函数接收不定数量的参数。下面具体介绍C/C++可变参数表的使用方法,使我们的函数也能支持这种不定参数。

先贴一个函数的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}

这个函数的功能很简单,就是找出一组int数里面的最大值并返回,不过大家可以看到这个函数采用了不定参数的实现形式(这个函数没什么实用性,仅供学习参考)。

上面的函数里有3个陌生的函数va_list、 va_arg、 va_end ,这其实是三个宏,头文件是”stdarg.h” 。三个宏的声明如下:

1
2
3
void va_start ( va_list arg_ptr, prev_param );
type va_arg ( va_list arg_ptr, type );
void va_end ( va_list arg_ptr );

通过va_start宏我们可以取得可变参数表的首指针,va_arg宏的意思则指取出当前arg_ptr所指的可变参数并将ap指针指向下一可变参数,而va_end宏被用来结束可变参数的获取。

说了这些大家应该就能看懂上面的max()函数了。函数的用法如下:

1
int n = max ( 5, 12, 6 ,3 ,8 ,5); /* 求5个整数中的最大值 */

第一个参数5即表示再后面的5个数里找到最大值。这个函数的实现很简单,首先通过va_start获取可变参数表,然后根据第一个固定参数num知道表中有5个不定参数,所有只要循环调用va_arg将参数读出来即可,最后调用va_end关闭参数表。

上面的实例虽然简单,但这是因为第一个参数给定了不定参数的个数,并且参数的类型默认全部为int。但是在printf()函数中,我们事先不能知道参数的个数,而且各个参数的类型也是不一样的,这种情况下处理起来就很麻烦了,只能由格式字符串进行识别(由%f、%d、%s等确定),这种情况下函数的处理过程一般是这样的:按顺序遍历字符串format(第一个固定参数可以直接得到),对每一个字符进行分支处理,决定如何从不定参数表中取参数。伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
while (*format)
{
     switch (*format)
     {
     case '%':  //转义字符
          format ++;
          switch(*format)
          {
               case 'd': //%d 表示对应的参数的int
                    ...;  //从参数表取出参数,类型转换为int
                    format ++;
                    break;
               case 'f': //%f 表示对应的参数的float
                    ...;  //从参数表取出参数,类型转换为float
                    format ++;
                    break;
               ..................
               default:
                    //下一个字符不是d、f、s等,说明不是转义字符,继续
                    break;
          }
          break;
     default:
          //不是转义字符或其他不需要处理的字符,跳过
          format ++;
          break;
     }
}

原创文章,转载请注明:转载自ian的个人博客[http://www.icodelogic.com]
本文链接地址: http://www.icodelogic.com/?p=72

tags:

2条评论

  1. Anne 说:

    博主很强大,我支持

发表评论

你需要先 登录 才能回复