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

目录
相关文章
|
7月前
|
Shell Linux
【Linux】Pass arguments into a function(一)
【Linux】Pass arguments into a function
53 0
|
7月前
|
Shell Linux
【Linux】Pass arguments into a function
【Linux】Pass arguments into a function
58 0
|
7月前
|
Shell Linux
【Linux】Pass arguments into a function(二)
【Linux】Pass arguments into a function
67 0
【Linux】Pass arguments into a function(二)
|
安全 C语言
警告 1 warning C4996: ‘scanf‘: This function or variable may be unsafe.
警告 1 warning C4996: ‘scanf‘: This function or variable may be unsafe.
|
NoSQL Redis
node-redis:ErrorReply: ERR wrong number of arguments for ‘auth‘ command
node-redis:ErrorReply: ERR wrong number of arguments for ‘auth‘ command
422 0
|
C++
warning C4996 sprintf This function or variable may be unsafe
warning C4996 sprintf This function or variable may be unsafe
87 0
|
安全
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
336 0
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
VS2017报错:严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C4996 'strcpy': This function or variable may be unsafe. Consid
VS2017报错:严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C4996 'strcpy': This function or variable may be unsafe. Consid
694 0
流水灯--使用现成的intrins.h中_crol_(variable,number)来实现八位IO口的单个低电平循环
使用现成的intrins.h中_crol_(variable,number)来实现八位IO口的单个低电平循环
253 0

热门文章

最新文章