Preprocessor Macros which operate on macros?
Here is 开发者_运维百科a sample of my macros:
#define STR(val) #val
#define STRX(val) STR(val)
#define LINE_ STRX(__LINE__)
#define SRC_STR __FILE__":"LINE_
#define SRC_STRN SRC_STR"\n"
#define PRINT_IF(cond) ((cond)&&(printf("\""#cond"\" is true: "SRC_STRN)>=0))
#define PRINT_IFNOT(cond) ((!(cond))&&(printf("\""#cond"\" is false: "SRC_STRN)>=0))
#define PRINT_IFN PRINT_IFNOT
#define PRINT_IFEQ(a,b) PRINT_IF(a==b)
#define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val)
#define PRINT_INT(i) PRINT_FMT(i,%d)
#define PRINT_LONG(i) PRINT_FMT(i,%ld)
#define PRINT_UINT(i) PRINT_FMT(i,%u)
#define PRINT_ULONG(i) PRINT_FMT(i,%lu)
#define PRINT_HEX(i) PRINT_FMT(i,%x)
#define PRINT_FLT(flt) PRINT_FMT(flt,%g)
#define PRINT_PTR(ptr) PRINT_FMT(ptr,%p)
#define PRINT_STR(str) PRINT_FMT(str,%s)
I want to define another list of macros related to this one, but I'd like to avoid having to type everything. I've already written one example:
#ifndef UNITTEST
#define PRINT_INT_U(x) ((void)sizeof(x))
#else
#define PRINT_INT_U(x) PRINT_INT(x)
#endif
You can see that I want my PRINT_
..._U
functions to evaluate to nothing when I am not running unit tests, so that I can spam it and not worry about them popping up all over the place during debug or production.
So my question is, is there some crazy method using the preprocessor to generate new #define statements? My guess is that there is not...
edit: Could I at least do something like this? make a list:
INT
LONG
UINT
ULONG
HEX
FLT
PTR
STR
and then insert them all each into the pattern
#define PRINT_%LI%_U(x) PRINT_%LI%(x)
where %LI%
represents an item from the list.
You don't need to change the definition of all of the PRINT_TYPE
macros: since they all delegate to PRINT_FMT
, you just need to change the definition of that macro.
#ifndef UNITTEST
#define PRINT_FMT(unused, unused) 0
#else
#define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val)
#endif
(printf
returns int
, so for consistency it makes sense to have the no-op version have type int
.)
How about something like this:
#include <stdio.h>
#define FLAG
#ifdef FLAG
#define SW(x,...) x##_1(__VA_ARGS__)
#else
#define SW(x,...) x##_0(__VA_ARGS__)
#endif
#define TEST1(a) SW(TEST1,a)
#define TEST1_0(a) 10
#define TEST1_1(a) 11
#define TEST2(a,b) SW(TEST2,a,b)
#define TEST2_0(a,b) 20
#define TEST2_1(a,b) 21
#define TEST3() 32
int main( void ) {
printf( "1. TEST1 = %i\n", TEST1(1) );
printf( "2. TEST2 = %i\n", TEST2(1,2) );
printf( "3. TEST3 = %i\n", TEST3() );
}
Its possible to define SW1,SW2 etc by number of arguments instead of variadic macros.
I hope its clear enough that its possible to define SW() to universally disable all macros, depending on flag value. But macro "definitions" (via SW) and "implementations" still need different names (there's no "macro overloading"), and its impossible to put a #define into a macro.
But its certainly not necessary to write a separate #ifdef for each macro.
Though not quite satisfactorily, at the least, the following code reuses the format specifier part. I'm not sure this can really help you, but just in case this can be a hint:
#define INT %d
#define LONG %ld
...and so forth...
#define PRINT(val,fmt) printf(#val" = "STRX(fmt)": "SRC_STRN,val)
#ifndef UNITTEST
#define PRINT_U(x,fmt) ((void)sizeof(x))
#else
#define PRINT_U(x,fmt) PRINT(x,fmt)
#endif
int i;
long l;
PRINT( i, INT );
PRINT( l, LONG );
PRINT_U( i, INT );
Hope this helps
精彩评论