woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

可变参数传递方法

       有时候,我们写函数的时候,可能遇到参数数量不确定的情况,这样的函数例如Cprintf打印函数。你可以使用printf("some string"), 也可以使用printf("%d", aintvalue)。是不是C的库里包含了不同定义的printf函数呢?答案肯定是否定的,因为C是不支持函数的重载的。每个函数只能由一个版本。那么是如何实现类似这种可变参数传递的函数呢?在这讲三种方法。

1)方法1:使用va_list
         
涉及到如下变量和函数(摘自msdn):
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
:参数类型
arg_ptr
:指向参数列表的指针
prev_param
:第一个参数的类型

         下面采用msdn里的一个例子。

1.        /* VA.C: The program below illustrates passing a variable

2.        * number of arguments using the following macros:

3.        *      va_start            va_arg              va_end

4.        *      va_list             va_dcl (UNIX only)

5.        */

6.         

7.        #include <stdio.h>

8.        #define ANSI            /* Comment out for UNIX version     */

9.        #ifdef ANSI             /* ANSI compatible version          */

10.    #include <stdarg.h>

11.    int average( int first, ... );

12.    #else                   /* UNIX compatible version          */

13.    #include <varargs.h>

14.    int average( va_list );

15.    #endif

16.     

17.    void main( void )

18.    {

19.       /* Call with 3 integers (-1 is used as terminator). */

20.       printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );

21.     

22.       /* Call with 4 integers. */

23.       printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );

24.     

25.       /* Call with just -1 terminator. */

26.       printf( "Average is: %d\n", average( -1 ) );

27.    }

28.     

29.    /* Returns the average of a variable list of integers. */

30.    #ifdef ANSI             /* ANSI compatible version    */

31.    int average( int first, ... )

32.    {

33.       int count = 0, sum = 0, i = first;

34.       va_list marker;

35.     

36.       va_start( marker, first );     /* Initialize variable arguments. */

37.       while( i != -1 )

38.       {

39.          sum += i;

40.          count++;

41.          i = va_arg( marker, int);

42.       }

43.       va_end( marker );              /* Reset variable arguments.      */

44.       return( sum ? (sum / count) : 0 );

45.    }

46.    #else       /* UNIX compatible version must use old-style definition.  */

47.    int average( va_alist )

48.    va_dcl

49.    {

50.       int i, count, sum;

51.       va_list marker;

52.     

53.       va_start( marker );            /* Initialize variable arguments. */

54.       for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )

55.          sum += i;

56.       va_end( marker );              /* Reset variable arguments.      */

57.       return( sum ? (sum / count) : 0 );

58.    }

59.    #endif

          通过上面的例子可以清楚知道怎么传递可变参数了。

2)方法2:利用参数入栈原理  
        
在现有的32位的机器上,一般通过将参数按照由低地址到高地址的顺序依次入栈实现传递,因此把第一参数的指针依次增加,就可以得到后面的参数了。例如:

1.        struct s1 

2.        {

3.            int a;

4.            char b;

5.        };

6.         

7.        struct s2 

8.        {

9.            int a;

10.    };

11.     

12.    void function (struct s1 a, ...) 

13.    {

14.        struct s1*  pa = &a;

15.        printf("%d, %c\n", pa->a, pa->b);

16.        ++pa;

17.        printf("%d, %c\n", pa->a, pa->b);

18.        ++pa;

19.        printf("%d\n", (struct s2*)pa->a);  //强制转换为struct s2类型

20.    }

21.    void main( void )

22.    {

23.        struct s1 a1 = {1, 'A'};

24.        struct s1 a2 = {2, 'B'};

25.        struct s2 a3 = {10};

26.        function(a1, a2, a3); //a3的类型不同于a1 a2

27.        return;

28.    }

29.     

        用这种方法传递可变参数非常简单。


3)方法3:用数组传参

 

1.        void   function(Type a[])   

2.        {   

3.          ...   

4.          a[0];    

5.          a[1];   

6.          ...   

7.        }

这种方法就不唠叨了,相信地球人都知道。       

 

posted on 2009-08-12 12:57 肥仔 阅读(2489) 评论(0)  编辑 收藏 引用 所属分类: C++ 基础


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理