标签:
1,介绍variadic function
可变参数的函数就是参数数量可以改变的函数。例如printf();
int printf(const char *format, ...);
printf("%d%s\n",i,s);
C语言之所以可以支持可变参数函数,一个重要的原因是C调用规范中规定C语言函数调用时,参数是从右向左压入栈的;这样一个函数实现的时候,就无需关心调用他的函数会传递几个参数过来,而只要关心自己用到几个;
例子:
#include<stdarg.h>
void print_int(int args,...)
{
va_list ap; //va_list 用来保存传给函数的其他参数。
va_start(ap,args); //说明可变参数从哪里开始
for(int i=0;i<args;i++){
printf("argument: %i\n",va_arg(ap,int));
}
va_end(ap);
}
这里用到一系列宏来帮助完成可变参数函数参数:va_start、va_arg和va_end;
在ANSI C标准下,这些宏定义在stdarg.h中。三个宏的原型如下:
void va_start(va_list ap, last);//取第一个可变参数(如上述printf中的i)的指针给ap,last是函数声明中的最后一个固定参数(比如printf函数原型中的*fromat);
type va_arg(va_list ap, type);//返回当前ap指向的可变参数的值,然后ap指向下一个可变参数;type表示当前可变参数的类型(支持的类型位int和double);
void va_end(va_list ap);//将ap置为NULL
2,陷阱
贴出一个计算一个账单的程序(来自嗨翻C语言),ABCD分别是四种酒水的名字。但是每位客人可能只点一种,也可能点某几种酒水。所以参数不定。
enum drink{A,B,C,D};//定义枚举类型
double price(enum drink d){ //每种酒水的价钱
switch(d){
case A:
return 6.79;
case B:
return 5.31;
case C:
return 4.82;
case D:
return 5.89;
}
return 0;
}
double total(int args,...)//核心程序,算出总的价钱。
{
double total=0;
va_list ap;
va_start(ap,args);
int i;
for(i=0;i<args;i++){
enum drink d=va_arg(ap,enum drink);//问题出在这个enum drink 上,将其改为int就出结果了,当然类型不匹配也会出现警告,但没办法,这就是缺陷所在了。
total+=price(d);
}
va_end(ap);
return total;
}
问题来了:编译时,出现warning: `drink‘ is promoted to(提升为) `int‘ when passed through `...‘(so you should pass `int‘ not `drink‘ to `va_arg‘)
if this code is reached, the program will abort.
而且这个程序打印不出total的价格,运行崩溃。
书中的解答:
va_arg宏的第2个参数不能被指定为char、short或者float类型。《C和C++经典著作:C陷阱与缺陷》在可变参数函数传递时,因为char和short类型的参数会被提升为int类型,而float类型的参数会被提升为double类型 。
标签:
原文地址:http://www.cnblogs.com/ypsun/p/4428121.html