Search code examples
cmacrosc-preprocessorcomma-operator

How does the following va_arg macro work?


I am reading a stdarg.h (link below) header file which defines the va_arg macro as follows

/*
 * Increment ap to the next argument in the list while returing a
 * pointer to what ap pointed to first, which is of type t.
 *
 * We cast to void* and then to t* because this avoids a warning about
 * increasing the alignment requirement.
 */
#define va_arg(ap, t)                   \
 (((ap) = (ap) + __va_argsiz(t)),       \
  *((t*) (void*) ((ap) - __va_argsiz(t))))

The line

((ap) = (ap) + __va_argsiz(t))

reassigns the value of ap however I don't understand the purpose of the comma or the line

*((t*) (void*) ((ap) - __va_argsiz(t)))

Link to stdarg.h file


Solution

  • We need to return to the caller what ap has been pointed to, and advance ap. An equivalent would be

        old_ap = ap
        ap = ap + argsiz
        return *old_ap
    

    However, that would require an extra variable, which is very hard (if possible) deal with in a macro in a portable way. Instead, the macro relies on a comma expression. It advances ap, and then computes its old value, which becomes a value of the comma expression, that is of the entire macro.