有些时候可能需要函数能够接收任意个参数, 比方说fprintf()函数,
int fprintf(FILE *stream, const char *format, ...);
... 表示的是任意个数的参数.
类似的还有execl和execlp :
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
要写一个可以接收任意个参数的函数, 要用到stdarg.h
例1 :
void print_ints(int args, char * name, ...) 这个函数里面, 至少要有一个固定的参数, 因为va_start宏需要知道...参数是这个固定参数后面开始的.
在va_start执行后, 每执行一次 va_arg 将依次返回...里面的参数的值。
va_arg的第二个参数代表正在获取的参数的类型, 如本例是int. 当然, 如果你传入的...里面包含了int, char 或者其他的类型的话, 调用va_arg则需要注意了.
args在这里被用于表示...里面有几个参数, 如果args的值小于真正传入的...参数个数, 会造成末端的参数读不到. 如果是大于真正传入的参数个数,
则可能得到不可预知的值.
[root@db-172-16-3-150 zzz]# cat a.c
#include <stdio.h>
#include <stdarg.h>
void print_ints(int args, char * name, ...) {
va_list ap;
va_start(ap, name);
int i;
for (i=0; i<args; i++) {
fprintf(stdout, "%s : %i\n", name, va_arg(ap, int));
}
va_end(ap);
}
int main() {
char * name = "digoal";
print_ints(3, name, 100, 99, 88);
name = "DIGOAL";
print_ints(6, name, 100, 99, 88, 77, 66, 55, 44);
return 0;
}
结果 :
[root@db-172-16-3-150 zzz]# gcc -O3 -Wall -Wextra -Werror -g ./a.c -o a && ./a
digoal : 100
digoal : 99
digoal : 88
DIGOAL : 100
DIGOAL : 99
DIGOAL : 88
DIGOAL : 77
DIGOAL : 66
DIGOAL : 55
// args=6, 实际...里面有7个参数, 所以最后的44未打印.
DIGOAL : 100
DIGOAL : 99
DIGOAL : 88
DIGOAL : 77
DIGOAL : 66
DIGOAL : 55
DIGOAL : 44
DIGOAL : 1604442516
DIGOAL : 4195328
DIGOAL : 105026360
// args=10, 实际...里面有7个参数, 所以多打印了3个, 这个是从print_ints这个函数的stack内存区域读出来的值, 没有意义.
重点 :
va_list ap;
va_start(ap, name);
va_arg(ap, 类型);
va_end(ap);
例2 :
计算商品总值.
[root@db-172-16-3-150 zzz]# cat a.c
#include <stdio.h>
#include <stdarg.h>
typedef enum drink {
MUDSLIDE,
FUZZY_NAVEL,
MONKEY_GLAND,
ZOMBIE
} drink;
double price (drink d) {
switch(d) {
case MUDSLIDE:
return 6.79;
case FUZZY_NAVEL:
return 5.31;
case MONKEY_GLAND:
return 4.82;
case ZOMBIE:
return 5.89;
}
// others return 0
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);
total = total + price(d);
}
va_end(ap);
return total;
}
int main() {
fprintf(stdout, "price is %.2f\n", total(2, MUDSLIDE, FUZZY_NAVEL));
fprintf(stdout, "price is %.2f\n", total(4, MUDSLIDE, FUZZY_NAVEL, MONKEY_GLAND, ZOMBIE));
return 0;
}
[root@db-172-16-3-150 zzz]# gcc -O3 -Wall -Wextra -Werror -g ./a.c -o a && ./a
price is 12.10
price is 22.81