Newsgroups: comp.std.c Path: utzoo!utgpu!jarvis.csri.toronto.edu!ephemeral.ai.toronto.edu!bradb From: bradb@ai.utoronto.ca Subject: Summary of variable args in macros Message-ID: <89May3.114634edt.10803@ephemeral.ai.toronto.edu> Reply-To: bradb@ai.utoronto.ca Organization: Department of Computer Science, University of Toronto Date: Wed, 3 May 89 11:46:29 EDT I recieved a number of replies about my query regarding variable numbers of parameters in macros. As I suspected, everyone told me that I can't do it, and that's OK, but I did get some interesting workarounds. The two approaches were to trick the macro expander into thinking it only has one argument that is made up of some macros that themselves expand into commas. Ick, but it works. The other approach is to pass an entire statement. I'd thought of that one, and it's a lot more general, but it too seems to be an ugly hack. Just in case anyone is interested, I gave up on variable-argument macros and wrote trace(), which prints a message, and traceVal(), which prints the value of a variable. Oh well. --------------------------------------------------------------------- Geoff Clare writes: Most replies you get will probably suggest using double parentheses like this: #define trace(s) (void) fprintf s trace( (stderr, "Entering zot(), arg is %d", arg) ); However, I prefer to use the following trick: #define _ , #define trace(s) (void) fprintf( stderr, s ) trace( "Entering zot(), arg is %d" _ arg ); ^ note: this space must be there ---------------------------------------------------------------------- David Keppel suggests passing the entire argument list to printf as a parameter: If you're really in to sadism (but bewarned: I warned you!) #define BLETCH(x) printf x ... BLETCH (("arg %d\n", arg)); ... BLETCH (("no arg\n")); You'll find life *much* easier if you can do something like STMT. I think that you probably can, even in this bizzare case. #define STMT(s) do { s } while(0); #define BLETCH(x) STMT(x) ... BLETCH (("arg %d\n", arg);); ... BLETCH (("no arg\n");); ---------------------------------------------------------------------------- Mark Brader says pretty much the same thing as Geoff: Right, you can't do it. The standard workaround is: #define trace(s) fprintf s trace((stderr, "Entering zot(), arg is %d\n", arg)); Notice the double parentheses; notice that the stderr has to be in the call. People who use this tend to use it with printf() rather than fprintf(), for just that reason. As a matter of readability, it's better to make macros expand to expressions rather than statements wherever possible -- because they look like function calls and function calls are expressions -- so your first version would have been better written with the "{" and "; }" omitted, as I have done in mine. ------------------------------------------------------------------------- Thanks again to all. (-: Brad Brown :-) bradb@ai.toronto.edu