我想在c中编写一个使用elipsis(...)参数的函数,但我不知道它是如何工作的。
我想做这样的事情:
void error(const char* fmt, ...);
void error(const char* fmt, ...) {
// fprintf(stderr, fmt, ...); << didnt work!
fprintf(stderr, fmt, /* ??? */);
}
我想像普通的printf()调用一样使用它。
error("bla");
error("nr: %d", 42);
error("pi: %f", 3.1415);
我怎样才能将elipsis作为hole的东西访问并将其传递给下一个函数?
答案 0 :(得分:2)
如果我理解你的问题,你要找的是关于变量参数或https://developers.google.com/books/docs/overview?csw=1的信息。在C下,您将需要研究'stdargs.h'标题和相关的手册页。这是一个简单的例子,它采用任意数量的整数并返回平均值。
#include <stdarg.h>
float average(int v, ...)
{
va_list args;
int i = 0;
int num = 0;
va_start(args, v);
for (; v; v--){
i += va_arg(args, int);
num++;
}
va_end(args);
return (float)i/num;
}
答案 1 :(得分:2)
省略号不构成您可以直接处理或转发的任何方式的“包”。管理与任何函数参数不匹配的函数参数的唯一方法是通过<stdarg.h>
功能。
这意味着对于每个变量函数foo
,您还应始终使用消耗vfoo
的相应函数va_list
。例如:
#include <stdarg.h>
void foo(const char * fmt, ...);
void vfoo(const char * va_list ap);
前者通常以后者的形式实施:
void foo(const char * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfoo(fmt, ap);
va_end(ap);
}
幸运的是,printf
系列函数遵循这些规则。因此,当您想要转移到printf
函数时,实际上使用了相应的基础vprintf
版本:
void error(const char * fmt, ...)
{
do_stuff();
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
当然遵循相同的规则,您应首先编写verror
函数,然后拨打vprintf
:
void verror(const har * fmt, va_list ap)
{
do_stuff();
vfprintf(stderr, fmt, ap);
}
答案 2 :(得分:2)
有关处理具有可变参数的函数,请参阅stdarg.h
。
对于简单地将可变数量的参数传递给fprintf
的特定情况,有vfprintf
,例如,
void error (const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
对于这种简单的情况,你也可以考虑变量宏(在C99中引入),例如,
#define error(fmt, ...) fprintf(stderr, "Error: " fmt, __VA_ARGS__)