variable number of arguments function

有些时候可能需要函数能够接收任意个参数, 比方说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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值