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
时间: 2024-11-01 01:43:32

variable number of arguments function的相关文章

mysql 存储过程 incorrect number of arguments

mysql教程 存储过程 incorrect number of arguments DROP PROCEDURE `chaxun_name_ps教程`// CREATE DEFINER=`root`@`localhost` PROCEDURE `chaxun_name_ps`(in c_id int,out c_phone char,out c_pwd char)     READS SQL DATA begin select phone,pwd from caopanshou where i

array variable used in printf function

在C中, array变量和指针极其相似. 指针加减运算, 首先需要知道指针类型, 类型占用的字节数, 如int *的指针, 加1 则表示地址加4字节(假设32位的机器int占4字节); 如果是char * 的指针, 指针变量加1则表示地址加1字节(char 占1个字节). 例子1 :  #include <stdio.h> #include <stdlib.h> int main() { char a[10] = "abcdefg"; printf("

Invalid number of arguments passed into method 方法名 - expected 1,but was 2

问题描述 C#开发的程序一直运行正常,最近偶尔出现标题中的异常,导致客户端程序所有用户都用不了,把上次发布的版本重新发布后就正常了.报错的"方法"在Webservice接口中,很久以前的版本中就已经改成2个参数的了.为了验证是否被别人把接口程序替换掉了,检查后发现文件时间都对的上没动过.我新建一个程序引用webservice接口,生成的方法也是2个参数的,但是调用时还是报"Invalidnumberofargumentspassedintomethod方法名-expected

数据库案例集锦 - 开发者的《如来神掌》

背景 「剑魔独孤求败,纵横江湖三十馀载,杀尽仇寇,败尽英雄,天下更无抗手,无可柰何,惟隐居深谷,以雕为友.呜呼,生平求一敌手而不可得,诚寂寥难堪也.」 剑冢中,埋的是剑魔独孤求败毕生几个阶段中用过的几柄剑: 利剑无意:第一柄是青光闪闪的利剑,凌厉刚猛,无坚不摧,弱冠前以之与河朔群雄争锋. 软剑无常:第二柄是紫薇软剑,三十岁前所用,误伤义士不祥,悔恨不已,乃弃之深谷. 重剑无锋:第三柄是玄铁重剑,重剑无锋,大巧不工,四十岁之前恃之横行天下. 木剑无俦:第四柄是已腐朽的木剑. 无剑无招:四十岁后,不

VB.NET and C# 语法比较手册

比较|语法 VB.NET and C# ComparisonThis is a quick reference guide to highlight some key syntactical differences between VB.NETand C#. Hope you find this useful!Thank you to Tom Shelton, Fergus Cooney, and others for your input. Comments Data Types Consta

C#和VB.net语法对比

C#和VB.net的语法相差还是比较大的. 可能你会C#,可能你会VB. 将它们俩放在一起对比一下你就会很快读懂,并掌握另一门语言. 相信下面这张图会对你帮助很大. Comments VB.NET 'Single line only Rem Single line only C# // Single line /* Multiple line */ /// XML comments on single line /** XML comments on multiple lines */ Data

python function with variadic arguments or keywords(dict)

一个*表示普通的任意个数的参数. 两个*表示dict类型的任意个数的参数. dict用法见 https://docs.python.org/3/library/stdtypes.html#typesmapping >>> keywords = dict(a=1, b=2) >>> a=100 >>> keywords = dict(a=1, b=2)   #或者使用{k:v, k:v}来构造 >>> keywords[a] Trace

redis4.0之module API

Modules API reference RedisModule_Alloc void *RedisModule_Alloc(size_t bytes); Use like malloc(). Memory allocated with this function is reported in Redis INFO memory, used for keys eviction according to maxmemory settings and in general is taken int

宏定义中的##操作符和... and _ _VA_ARGS_ _

1.Preprocessor Glue: The ## Operator 预处理连接符:##操作符 Like the # operator, the ## operator can be used in the replacement section of a function-like macro.Additionally, it can be used in the replacement section of an object-like macro. The ## operator co