C Language Preprocessor and Macros Variadic arguments macro


Example

C99

Macros with variadic args:

Let's say you want to create some print-macro for debugging your code, let's take this macro as an example:

#define debug_print(msg) printf("%s:%d %s", __FILE__, __LINE__, msg)

Some examples of usage:

The function somefunc() returns -1 if failed and 0 if succeeded, and it is called from plenty different places within the code:

int retVal = somefunc();

if(retVal == -1)
{
    debug_printf("somefunc() has failed");
}

/* some other code */

 retVal = somefunc();

if(retVal == -1)
{
    debug_printf("somefunc() has failed");
}

What happens if the implementation of somefunc() changes, and it now returns different values matching different possible error types? You still want use the debug macro and print the error value.

debug_printf(retVal);      /* this would obviously fail */
debug_printf("%d",retVal); /* this would also fail */

To solve this problem the __VA_ARGS__ macro was introduced. This macro allows multiple parameters X-macro's:

Example:

 #define debug_print(msg, ...) printf(msg, __VA_ARGS__) \
                               printf("\nError occurred in file:line (%s:%d)\n", __FILE__, __LINE)

Usage:

int retVal = somefunc();

debug_print("retVal of somefunc() is-> %d", retVal);

This macro allows you to pass multiple parameters and print them, but now it forbids you from sending any parameters at all.

debug_print("Hey");

This would raise some syntax error as the macro expects at least one more argument and the pre-processor would not ignore the lack of comma in the debug_print() macro. Also debug_print("Hey",); would raise a syntax error as you cant keep the argument passed to macro empty.

To solve this, ##__VA_ARGS__ macro was introduced, this macro states that if no variable arguments exist, the comma is deleted by the pre-processor from code.

Example:

 #define debug_print(msg, ...) printf(msg, ##__VA_ARGS__) \
                               printf("\nError occured in file:line (%s:%d)\n", __FILE__, __LINE)

Usage:

 debug_print("Ret val of somefunc()?");
 debug_print("%d",somefunc());