Question

Currently, I have a very simple function to deallocate array of doubles in my program:

void deallocate(double** array)
{
    free(*array);
}

I would like this function to be variadic in order to take several arrays, and free them one after another. I've never written a variadic function, and as there may exist tricks with pointers I would like to know how to do that.

Was it helpful?

Solution

Don't do this with a variadic function, this concept should be retired. In particular it makes no sense at all for something that is to receive arguments of all the same type, void*.

Just have a simple function, first that receives an array of pointers

void free_arrays(void* a[]) {
  for (size_t i = 0; a[i]; ++i) free(a[i]);
}

Then you can wrap that with a macro like that

#define FREE_ARRAYS(...) free_arrays((void*[]){ __VA_ARGS__, 0 })

This supposes that none of your pointers is already 0, since the processing would stop at that point.

If you'd have a need to have that working even if some of the pointers are 0, you'd have to pass the number of elements as a first parameter to your function. This is a bit tedious but can be determined in the macro, too.

void free_arrays0(size_t n, void* a[]) {
  for (size_t i = 0; i < n; ++i) free(a[i]);
}

#define FREE_ARRAYS0(...)                                    \
  free_arrays(                                               \
              sizeof((void*[]){ __VA_ARGS__})/sizeof(void*), \
              (void*[]){ __VA_ARGS__}                        \
             )

OTHER TIPS

You can do it like this:

void deallocate(double *p, ...)
{
    va_list ap;

    va_start(ap, p);
    do {
        free(p);
        p = va_arg(ap, double *);
    } while (p);
    va_end(ap);
}

Call as deallocate(p1, p2, p3, (double *)NULL). You need the NULL (or some other value) as a sentinel to signal the end of the argument list; none of the other pointers should be NULL or the loop will stop prematurely.

I'm not saying that this is a good idea, though: varargs functions have their use cases, but they're error-prone with pointers because some implicit conversions don't take place (because the compiler doesn't know the type of the arguments beyond the first).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top