C语言可变参数全解
3977 点击·0 回帖
![]() | ![]() | |
![]() | cstdarg(stdarg.h) 可变参数的处理 这个头文件定义了一些宏,可以通过这些宏来逐个访问被调函数的没有名字的参数列表,这些参数的个数 和类型都是不知道的。 一个函数可以通过包含一个逗号和三个点(,...)接收可变数量的额外参数,而不需要给出相应的参数定义。 这些可变参数必须出现在常规命名参数的后面。 返回值 函数名 (参数声明 , ...); 可以通过该头文件中定义的宏va_start, va_arg和va_end来访问额外的参数。 *首先,va_start初始化了一个名为va_list的可变参数列表; *序列的执行va_arg将会按照参数传递给函数的顺序产生额外参数的值; *最胡,va_end必须在函数返回之前被执行。 该头文件包含了一个类型: va_list 包含可变参数信息的类型。(类型) 三个函数: va_start 初始化一个可变参数列表。(宏) va_arg 获取下一个参数。 (宏) va_end 停止使用可变参数列表。 (宏) 一些C编译器的实现(例如ISO C99兼容的编译器)同样也包含一个va_copy宏,用于复制一个va_list对象, 但是这并不是ISO C++标准的一部分。 va_start void va_start (va_list ap, paramN); 初始化可变参数列表 初始化最为参数传入的va_list类型的对象ap,ap保存了通过va_arg获得参数paramN之后的可变参数的 信息。 一个函数执行了va_start,就必须在函数返回之前执行va_end。 参数 ap va_list类型的对象,保存了通过va_arg获取可变参数的信息。 paramN 函数定义的最后一个命名参数的名字。 返回值 无 示例 [cpp] <span style="font-size:16px;">/* va_start example */ #include <stdio.h> #include <stdarg.h> void PrintFloats ( int amount, ...) { int i; double val; printf ("Floats passed: "); va_list vl; va_start(vl,amount); for (i=0;i<amount;i++) { val=va_arg(vl,double); printf ("\t%.2f",val); } va_end(vl); printf ("\n"); } int main () { PrintFloats (3,3.14159,2.71828,1.41421); return 0; }</span> <span style="font-size:16px;">/* va_start example */ #include <stdio.h> #include <stdarg.h> void PrintFloats ( int amount, ...) { int i; double val; printf ("Floats passed: "); va_list vl; va_start(vl,amount); for (i=0;i<amount;i++) { val=va_arg(vl,double); printf ("\t%.2f",val); } va_end(vl); printf ("\n"); } int main () { PrintFloats (3,3.14159,2.71828,1.41421); return 0; }</span> 这函数PrintFloats以amount作为它的第一个参数,代表额外参数的数量,将会通过cstaarg定义的宏读取, 并且以一种特殊的格式打印出来。 va_arg type va_arg ( va_list ap, type ) 获取下一个参数 这个宏展开成了一个表达式,该表达式包含着可变参数列表中下一个参数的类型和值。 下一次调用这个宏将会展开以同样顺序传递给函数的下一个参数。 注意va_arg不能决定传递给函数的参数的实际类型,但是可以以宏type的类型作为它的类型。 同样也需要注意va_arg不能决定此次获取的参数是否为传递给该函数的参数中的最后一个。函数必须如下 来设计:参数的数量必须可以通过已经读取的命名的或者是没命名的参数的值来确定。 参数 www.atcpu.com ap 一个va_list类型的对象。这个参数在va_arg调用之前,必须通过调用va_start来初始化。 type 一个类型名。这个类型名就是该宏展开后的表达式的类型(例如,它的返回类型)。一个合法的适合va_arg 使用的类型表达式必须如下:当一个*号添加到它的右边,那么它的结果表达式必须是一个合法的type类型的 指针。 返回值 以类型type的类型表达式返回下一个额外参数。 示例 [cpp] <span style="font-size:16px;">/* va_arg example */ #include <stdio.h> #include <stdarg.h> int FindMax ( int amount, ...) { int i,val,greater; va_list vl; va_start(vl,amount); greater=va_arg(vl,int); for (i=1;i<amount;i++) { val=va_arg(vl,int); greater=(greater>val)?greater:val; } va_end(vl); return greater; } int main () { int m; m= FindMax (7,702,422,631,834,892,104,772); printf ("The greatest one is: %d\n",m); return 0; }</span> <span style="font-size:16px;">/* va_arg example */ #include <stdio.h> #include <stdarg.h> int FindMax ( int amount, ...) { int i,val,greater; va_list vl; va_start(vl,amount); greater=va_arg(vl,int); for (i=1;i<amount;i++) { val=va_arg(vl,int); greater=(greater>val)?greater:val; } va_end(vl); return greater; } int main () { int m; m= FindMax (7,702,422,631,834,892,104,772); printf ("The greatest one is: %d\n",m); return 0; }</span> FindMax函数使用它的第一个参数保存将会获取到的额外参数的数量。第一个额外的参数被获取并且作为初始 的比较值,然后在一个循环里获取余下的参数并且返回其中最大的一个(在这里就是892)。 va_end void va_end( va_list ap ); 执行合适的动作,使得我们可以从使用了va_list类型对象ap获取额外参数的函数中正常返回。 无论va_start在之前的什么时候被执行,这个宏必须在函数返回之前执行。 参数 ap va_list对象,也就是之前通过va_start初始化的对象。 返回值 无 示例 [cpp] <span style="font-size:16px;">/* va_arg example */ #include <stdio.h> #include <stdarg.h> void PrintLines ( char* first, ...) { char* str; va_list vl; str=first; va_start(vl,first); do { printf ("%s\n",str); str=va_arg(vl,char*); } while (str!=NULL); va_end(vl); } int main () { PrintLines ("First","Second","Third","Fourth",NULL); return 0; }</span> <span style="font-size:16px;">/* va_arg example */ #include <stdio.h> #include <stdarg.h> void PrintLines ( char* first, ...) { char* str; va_list vl; str=first; va_start(vl,first); do { printf ("%s\n",str); str=va_arg(vl,char*); } while (str!=NULL); va_end(vl); } int main () { PrintLines ("First","Second","Third","Fourth",NULL); return 0; }</span> PrintLines函数使用了可变参数。第一个传递的参数是first,但是余下的参数都是在do-while循环中使用 va_arg一次获得了,该循环在获取的可变参数为null指针的时候结束。 | |
![]() | ![]() |