Is including stdarg.h necessary for "..." argument in header files?

Viewed 267
#ifndef WHATEVER_H
#define WHATEVER_H

void test(const char *format, ...); // would you have to #include <stdarg.h> for ... on argument, or is it ok if you don't use it

#endif // WHATEVER_H

So if I were to have a header file like this, where I needed to put ... as my argument for my void test function, would I have to include stdarg.h for the ... argument, or is it not mandatory?

2 Answers

The header does not need to include <stdarg.h> if the prototypes only include the ellipsis (, ...) notation. The code implementing the test() function will need to include <stdarg.h>, but the header declaring it need not.

However, you should often consider creating a second function, void vtest(const char *format, va_list args); to match the test() function in the header, and then you do need <stdarg.h> to define the va_list type (and the implementation code no longer needs a separate #include <stdarg.h>). With the vtest() declaration in the header, the implementation of the test() function becomes trivial:

void test(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    vtest(format, args);
    va_end(args);
}

This is particularly simple since there is no return value to relay, but returning a value is not very much harder. It's often a good idea to implement a variadic function like test() using this scheme, even if you don't expose the vtest() function — it is rather likely that you'll want the extra flexibility it provides eventually.

No you do not need to, but it will rather hard to access parameters hidden behind the ... without macros from this header.

you will need to know your implementation for example for gcc you can use:

__builtin_va_start(v,l)
__builtin_va_end(v)
__builtin_va_arg(v,l)
__builtin_va_copy(d,s)
Related