Search code examples
cgccstatic-analysisc89

Typesafe varargs in C with gcc


Many times I want a function to receive a variable number of arguments, terminated by NULL, for instance

#define push(stack_t stack, ...) _push(__VARARG__, NULL);
func _push(stack_t stack, char *s, ...) {
    va_list args;
    va_start(args, s);
    while (s = va_arg(args, char*)) push_single(stack, s);
}

Can I instruct gcc or clang to warn if foo receives non char* variables? Something similar to __attribute__(format), but for multiple arguments of the same pointer type.


Solution

  • I know you're thinking of using __attribute__((sentinel)) somehow, but this is a red herring.

    What you want is to do something like this:

    #define push(s, args...) ({                   \
      char *_args[] = {args};                     \
      _push(s,_args,sizeof(_args)/sizeof(char*)); \
    })
    

    which wraps:

    void _push(stack_t s, char *args[], int argn);
    

    which you can write exactly the way you would hope you can write it!

    Then you can call:

    push(stack, "foo", "bar", "baz");
    push(stack, "quux");