prev up next   top/contents search

comp.lang.c FAQ list · Question 10.26

Q: How can I write a macro which takes a variable number of arguments, or use the preprocessor to ``turn off'' a function call with a variable number of arguments?


A: One popular trick is to define and invoke the macro with a single, parenthesized ``argument'' which in the macro expansion becomes the entire argument list, parentheses and all, for a function such as printf:

	#define DEBUG(args) (printf("DEBUG: "), printf args)

	if(n != 0) DEBUG(("n is %d\n", n));
The obvious disadvantage is that the caller must always remember to use the extra parentheses. Another problem is that the macro expansion cannot insert any additional arguments (that is, DEBUG() couldn't expand to something like fprintf(debugfd, ...)).

gcc has an extension which allows a function-like macro to accept a variable number of arguments, but it's not standard. Other possible solutions are:

(These all require care on the part of the user, and all of them are rather ugly.)

C99 introduces formal support for function-like macros with variable-length argument lists. The notation ... can appear at the end of the macro ``prototype'' (just as it does for varargs functions), and the pseudomacro __VA_ARGS__ in the macro definition is replaced by the variable arguments during invocation.

Finally, you can always use a bona-fide function, which can take a variable number of arguments in a well-defined way. See questions 15.4 and 15.5. (If you needed a macro replacement, try using a function plus a non-function-like macro, e.g. #define printf myprintf .)

When you want to turn the debugging printouts off, you can either use a different version of your debug macro:

	#define DEBUG(args) /* empty */
or, if you're using real function calls, use still more preprocessor tricks to remove the function name but not the arguments, such as
	#define DEBUG (void)
or
#define DEBUG if(1) {} else printf or
#define DEBUG 1 ? 0 : (void)
(These tricks are predicated on the assumption that a good optimizer will remove any ``dead'' printf calls or degenerate cast-to-void parenthesized comma expressions.) See also question 10.14.

Additional links: more ideas

References: C9X Sec. 6.8.3, Sec. 6.8.3.1


prev up next   contents search
about this FAQ list   about eskimo   search   feedback   copyright

Hosted by Eskimo North