0

i want to write a function in c which uses the elipsis (...) argument, but i have no idea how it works.

i want to do something like this:

void error(const char* fmt, ...);

void error(const char* fmt, ...) {
  // fprintf(stderr, fmt, ...); << didnt work!
  fprintf(stderr, fmt, /* ??? */);
}

i want to use it like a "normal" printf() call.

error("bla");
error("nr: %d", 42);
error("pi: %f", 3.1415);

how can i access the elipsis as hole thing and pass it to the next function?

linluk
  • 1,650
  • 16
  • 33
  • 1
    Take a look [HERE](http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html) – LPs May 25 '15 at 14:00

3 Answers3

2

If I understand your question properly, what you're looking for is information on variable arguments or a Variadic Function. Under C you will want to research the 'stdargs.h' header and associated manual page. Here is a simple example that takes an arbitrary number of integers and returns the average.

#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;
}
David Hoelzer
  • 15,862
  • 4
  • 48
  • 67
2

The ellipsis does not constitute a "pack" in any way that you can handle or forward directly. The only way you can manage function arguments that don't match any function parameters is via the <stdarg.h> features.

This means that for every variable function foo you should also always have a corresponding function vfoo that consumes a va_list. For example:

#include <stdarg.h>

void foo(const char * fmt, ...);
void vfoo(const char * va_list ap);

The former is typically implemented in terms of the latter:

void foo(const char * fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vfoo(fmt, ap);
    va_end(ap);
}

Luckily, printf family of functions follows these rules. So when you want to farm out to a printf function, you actually use the corresponding underlying vprintf version:

void error(const char * fmt, ...)
{
    do_stuff();

    va_list ap;
    va_start(ap, fmt);

    vfprintf(stderr, fmt, ap);

    va_end(ap);
}

Of course following the same rules you should write a verror function first and make that one call vprintf:

void verror(const har * fmt, va_list ap)
{
    do_stuff(); 
    vfprintf(stderr, fmt, ap);
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

See stdarg.h for dealing with functions with variable arguments.

For the specific case of simply passing the variable number of arguments to fprintf, there is vfprintf for that, e.g.,

void error (const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
}

For such a simple case you may also consider variadic macros (introduced in C99), e.g.,

#define error(fmt, ...) fprintf(stderr, "Error: " fmt, __VA_ARGS__)
Arkku
  • 41,011
  • 10
  • 62
  • 84
  • The function doesn't "have" a variable number of arguments. Rather, it *can be called* with a variable number of arguments. (Functions don't have arguments, they have parameters. An ellipsis means that there may be arguments that don't match any of the parameters.) – Kerrek SB May 25 '15 at 14:08
  • @KerrekSB By language of the standard you are probably right, but I must say I don't see any practical difference to defining "having arguments" in a way such that a variadic function is said to have a variable number of arguments. (Anyhow, I changed the wording to "accepting a variable number of arguments" as that seems to be used in the standard.) – Arkku May 25 '15 at 14:15
  • The distinction is fairly important if you care about type safety, linkage, argument promotion, grammar, and semantics, but otherwise you're right, it's all just pedantry :-S – Kerrek SB May 25 '15 at 14:48
  • @KerrekSB Oh, come on, all of those concepts can be understood regardless of what it is called, it does not follow that one doesn't "care about" those things by calling it a function having a variable number of arguments, and given that the context is illustrated by an example and reference to `stdarg.h` there should be no room for confusion. Even the standard says "a function with variable number of arguments" (C11 7.1.4) – I see little distinction between "with" and "having". – Arkku May 25 '15 at 15:53
  • (In my opinion the use of "parameter" and "argument" to stand for "formal argument/parameter" and "actual argument/parameter", respectively, is also potentially confusing, since the usage is far from universal. Admittedly they are defined this way in the current C standard, but if it was expected that everyone had memorised the standard there would be little need for most of these questions… And in the special case of variable arguments, there are no corresponding formal parameters, yet clearly the function "has" them as part of its declaration, therefore it is with / has variable arguments?) – Arkku May 25 '15 at 16:05