What does the message ``warning: macro replacement within a string literal'' mean?
Some pre-ANSI compilers/preprocessors interpreted macro definitions like
#define TRACE(var, fmt) printf("TRACE: var = fmt\n", var)
such that invocations like
TRACE(i, %d);
were expanded as
printf("TRACE: i = %d\n", i);
In other words, macro parameters were expanded even inside string literals and character constants.
Macro expansion is not defined in this way by K&R or by Standard C. When you do want to turn macro arguments into strings, you can use the new # preprocessing operator, along with string literal concatenation (another new ANSI feature):
#define TRACE(var, fmt) printf("TRACE: " #var " = " #fmt "\n", var)
What's the best way to write a multi-statement macro?
ANSWER:
#define MACRO(arg1, arg2) do { \
/* declarations */ \
stmt1; \
stmt2; \
/* ... */ \
} while(0) /* (no trailing ; ) */
How can I write a macro which takes a variable number of arguments?
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.
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 to use different macros (DEBUG1, DEBUG2, etc.) depending on the number of arguments, to play games with commas:
#define DEBUG(args) (printf("DEBUG: "), printf(args))
#define _ ,
DEBUG("i = %d" _ i)
No comments:
Post a Comment