# f* Q/ B6 b: \, p1 G/ L$ FDefinitions for ACCESSing parameters in functions that accept* M. k6 G4 Q/ a5 f4 w! M
a variable number of arguments.( [% W# v9 k( D7 x/ ~6 k
. d @* s& c& n2 L2 A* k$ v6 dCopyright (c) Borland International 1987,1988 ' r4 k& C3 B7 h& [6 |$ TAll Rights Reserved. 0 \- Y/ B9 {% c* d* f L*/ 0 ^2 |% P7 C1 h2 J3 t# `#if __STDC__ I: n& e2 h; |) C9 ]. G
#define _Cdecl! Y7 u& o8 K/ ^4 K* d$ b9 E- }
#else 7 P( W6 k" g1 a$ M4 C, P#define _Cdecl cdecl6 n i& F3 c9 `% C/ G
#endif8 S3 H; a. F4 \( Z* h" O/ r( _, K
$ P/ H" i, Z5 t. Q; m, j
#if !defined(__STDARG)6 |. u q+ v. n; m; E
#define __STDARG. H8 @' Q( B& e( H6 k9 w5 Y
8 x# z5 K0 w$ A4 f& h- x. Otypedef void *va_list; 4 N7 o6 j5 r. n/ M& J+ t2 R5 i3 p
#define va_start(ap, parmN) (ap = ...)" [& M* H- f+ F" q3 ~8 }6 j8 c
#define va_arg(ap, type) (*((type *)(ap))++) ; I& Y& E2 d# G+ `# d#define va_end(ap)5 P: N! A) U3 o" g6 k
#define _va_ptr (...) A6 _) H8 r/ X% k5 y* s' u#endif $ @* ~8 U; k {2 z( A1 q; J& Q1 M6 {+ e' ?7 r
以上为"STDARG.H"的内容. 4 g; H. n5 Q9 {7 u6 o$ @该文件定义了使用可变参数所用到的数据类型:typedef void *va_list; 8 p5 d" f% p4 w% Cva_start(ap,parmN)起到初始化,使用得ap指向可变参数的第一个参数.ap的类型为va_list,. S0 K _2 I& B) X7 ?" ?
parmN为可变参数的前面一个固定参数. 1 K, }, |- o4 l$ f# ova_arg(ap,type)获得当前ap所指向的参数,并使ap指向可变参数的下一个参数,type为需要获得的参数的类型. 8 E) }: g& V! Zva_end(ap) 结束可变参数获取.0 {* S+ h' Z1 D. I8 }5 m/ J" j1 X
$ L3 a( u% u+ r' ?1 N4 T3)可变参数的使用实例) Z/ D( `/ q( \4 p/ U2 _; j
0 v& @3 ]8 u2 m# q
实例目的:用可变参数来实现个数不定的字符串的传递,并显示传递过来的字符串.! X5 v' w; x3 h$ {8 T! _2 H
7 b6 A" X: N0 ^+ h
#include<stdio.h> Y4 s9 n8 Y5 `
#include<conio.h>+ l" R! `( I( y9 D% s
#include<stdarg.h>/ `0 X* b* b" r% g% j; [" r
void tVarArg(int num,...);/*num为可变参数的个数*/. N8 B9 p/ C( l* W' l
int main(void) , r" C, o8 [) i4 a{1 z" Q* P) b% F; s( ?8 I
clrscr();8 X; ^0 q* D9 `! |9 a% e
tVarArg(5,"Hello! ","My ","name ","is ","neverTheSame.\n");* T, G( E# N, K, b( T# M5 c
tVarArg(8,"This ","is ","an ","example ","about ","variable-argument ","in ","funtion"); ! @4 Q+ I. x" y- xgetch();" N8 P3 V. \$ Q: \
return 0;, e1 H3 n2 e0 w3 e3 o
} 1 v4 y4 K6 K5 ]# [( o$ [void tVarArg(int num,...)$ p, A6 h9 \6 m+ p* U% O4 l/ \1 @
{ 9 _* Q& e+ O0 i1 H, d' k+ Vva_list argp; /*定义一个指向可变参数的变量*/ $ E6 J7 I7 t& I7 D. Iva_start(argp,num); /*初始化,使用argp指向可变参数的第一个参数*/( L$ V. B$ \* u! b
while(--num>=0)/ Y0 _; J/ ]' _+ ^* ^
printf("%s",(va_arg(argp,char*)));/*va_arg(argp,char*)获得argp所指向的参数, ) s. t x5 ?& x1 o" a$ Y9 T 并使用argp指向下一个参数,char*使用所获得的参数的类型转换为char*型.*/ + ^! W& T, N8 j7 v1 Ova_end(argp); /*结束可变参数获取*/8 p( S* M+ N8 K5 G
return ; 9 U9 M% D. {% P% p}) [% x# i( y3 L0 u
9 a" n' Y1 O9 k0 e, C% o
4)可变参数的使用需要注意的问题 . C7 }# r3 Q; U: v8 S5 X5 _& }/ h/ d. L3 w3 u8 L' K, h Z4 E
1.每个函数的可变参数至多有一个. 6 e8 |0 U+ S3 [+ y6 \' Z2.va_start(ap,parmN)中parmN为可变参数前的一个固定参数.( d: t+ H$ U% l/ x- P
3.可变参数的个数不确定,完全由程序约定. 5 ?) }: K. }- j* S' ~' g7 I; B, l( a5 Q5 \4.可变参数的类型不确定,完全由va_arg(ap,type)中的type指定,然后就把参数的类型强制转换. ! ?9 o# X1 {' n- Y而printf()中不是实现了识别参数吗?那是因为函数 * v7 S" I: {5 ^ Yprintf()是从固定参数format字符串来分析出参数的类型,再调用va_arg 0 @6 `+ ~4 M5 l. O的来获取可变参数的.也就是说,你想实现智能识别可变参数的话是要通 ! N( N& l o" o2 ?% \
过在自己的程序里作判断来实现的. - A1 `- F% X1 R- R. x# D2 l5 C5.编译器对可变参数的函数的原型检查不够严格,对编程人员要求很高.