可變參數傳遞方法
有時候,我們寫函數的時候,可能遇到參數數量不確定的情況,這樣的函數例如C的printf打印函數。你可以使用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 肥仔 閱讀(2505) 評論(0) 編輯 收藏 引用 所屬分類: C++ 基礎