#define blah #ifdef -help! (C not C++)

Programming, for all ages and all languages.
earlz

#define blah #ifdef -help! (C not C++)

Post by earlz »

I am attempting to make some debugging macros because I hate having to type #ifdef DEBUG it takes so long to type and it is not very pretty so I tried making some macros like this:

Code: Select all

//these just make it tons easier
#define DEBUG_ON #ifdef DEBUG
#define DEBUG_OFF #endif
//prints only if debugging
#define DBPRINT(string) \
     #ifdef DEBUG \
          printf("debug: ");\
          printf(string);\
     #endif
//end dbprint
I get # is not followed by a macro paremeter
and ifdef not declared and syntax error at #

so is this possible or do I have to do it the extremely ugly way
Kemp

Re:#define blah #ifdef -help! (C not C++)

Post by Kemp »

Think of this logically. Say you have:

Code: Select all

#define DEBUG_ON #ifdef DEBUG

DEBUG_ON
The pre-processor will run through it and the replace it to:

Code: Select all

#ifdef DEBUG
Which will then be sent to the compiler, which has no concept of what any of that means as it's not C code.

It's not that hard to use this:

Code: Select all

#define DBPRINT(string) \
          printf("debug: ");\
          printf(string);
and then in the code:

Code: Select all

#ifdef DEBUG
DBPRINT("foobar")
#endif
earlz

Re:#define blah #ifdef -help! (C not C++)

Post by earlz »

well the debug_on and off is my main thing I wanted
but for dbprint I figured why not do it like assert and the macro be blank if debug is not defined
Kemp

Re:#define blah #ifdef -help! (C not C++)

Post by Kemp »

The basic problem is that afaik you can't use pre-processor directives within pre-processor directives because it only does one pass, so the ones you're swapping the text to are passed to the compiler, which says "wtf? :o" and falls over.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:#define blah #ifdef -help! (C not C++)

Post by Solar »

Jordan3 wrote: #define DEBUG_ON #ifdef DEBUG
#define DEBUG_OFF #endif
Use [tt]#define DEBUG[/tt] or [tt]gcc -DDEBUG[/tt] instead. Kemp is right, you cannot "nest" preprocessor directives like that. Use [tt]gcc -E[/tt] to find out what your preprocessor does with your code here.

While you're at it, use NDEBUG instead of DEBUG - that way you can toggle assert() and your DBPRINT() with the same flag.
Every good solution is obvious once you've found it.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:#define blah #ifdef -help! (C not C++)

Post by Candy »

you could also change the logic:

Code: Select all

#ifdef DEBUG
#define DEBUG_ON if(1) {
#define DEBUG_OFF }
#else
#define DEBUG_ON if(0) {
#define DEBUG_OFF }
#endif

// note, you can use semicolons but you normally shouldn't.
DEBUG_ON
  printf("some debug thingy");
DEBUG_OFF
Or, what I might like more (not sure yet):

Code: Select all

#ifdef DEBUG
#define debug if(1)
#else
#define debug if(0)
#endif

// logical statement rather than plain defines
// needs people to know what debug does though.
debug {
  printf("some debug thingy");
}
earlz

Re:#define blah #ifdef -help! (C not C++)

Post by earlz »

Thanks so much!
I think i like the last method or well probably have both methods though
mystran

Re:#define blah #ifdef -help! (C not C++)

Post by mystran »

Alternatively you can have static inline functions like this

Code: Select all

#ifdef DEBUG
static inline void debug(char * x) {printk(x);}
#else
static inline void debug(char * x) {}
#endif
I like Candy's [tt]debug { ... }[/tt] syntax though, because it allows arbitary statements, and creates a new local scope for temporaries. Often figuring out the data-to-be-printed is more work than actually printing it.

The [tt]DEBUG_ON[/tt] / [tt]DEBUG_OFF[/tt] is IMHO worse because it too creates a scope without the [tt]{}[/tt] that would normally tell you there's one.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:#define blah #ifdef -help! (C not C++)

Post by Candy »

mystran wrote: I like Candy's [tt]debug { ... }[/tt] syntax though, because it allows arbitary statements, and creates a new local scope for temporaries. Often figuring out the data-to-be-printed is more work than actually printing it.
I'm liking it more & more too, it's in a way very clear about what it's doing (most people would claim you're modifying the language, it fits in that well) and it does exactly what you'd want it to do (so even if you don't know it, you can use it). This one's a keeper for me.
earlz

Re:#define blah #ifdef -help! (C not C++)

Post by earlz »

another thing is you can use the else command wiht it for releases
like this

Code: Select all

debug{
printf("This is a debug version...\n");
}else{
printf("This is a release version...\n");
}
though it might cause some confusion
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:#define blah #ifdef -help! (C not C++)

Post by Pype.Clicker »

Jordan3 wrote: though it might cause some confusion
i'd mostly fear that it become tempting to have real code in the "else { ... }" part, and that the "debugging" version differs not only by the verbosity level, but also by the nitty-gritty details of its implementation.
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re:#define blah #ifdef -help! (C not C++)

Post by df »

in my debugging system I have two parts.

Code: Select all

void _LogWrite(char *strFile, long lineno, char *strX, ...)
{
#ifndef NLOGWRITE
   va_list   args;

   va_start(args, strX);
   vsprintf(strLogBuffer, strX, args);
   printf("%s(%li) : %s", strFile, lineno, strLogBuffer);
   va_end(args);

   fflush(stderr);
#endif
}
and a macro

Code: Select all

#define   LogWrite(...) _LogWrite(__FILE__, __LINE__, __VA_ARGS__)
and I define NLOGWRITE in gcc if I need it.. gcc -DNLOGWRITE etc...

I also have another routine for the same thing which you pass a severity flag with it and it will only print logging messages over a certain level.. (user controlled. good for testing....)

so in my code I just use

Code: Select all

LogWrite("blah blah %i value of 0x%08lX", a, b);
-- Stu --
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:#define blah #ifdef -help! (C not C++)

Post by Solar »

One hint on that: Make sure your compiler is smart enough to optimize the call to _LogWrite() away to nothing when NLOGWRITE is defined, or be aware that even with logging disabled you're paying for a function call whenever _LogWrite() comes up.

This can get really nasty when you're applying this to C++ code, where converting a complex object to string (to satisfy operator<<() ) can get really expensive.
Every good solution is obvious once you've found it.
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re:#define blah #ifdef -help! (C not C++)

Post by df »

thats ok, I only write C not c++ so its safe ;) plus it never goes away as I use a VerbsoseWrite(level, .....) so I am always using it in some capacity..

thats not to say it couldnt be improved in several ways :)
-- Stu --
JoeKayzA

Re:#define blah #ifdef -help! (C not C++)

Post by JoeKayzA »

Solar wrote: This can get really nasty when you're applying this to C++ code, where converting a complex object to string (to satisfy operator<<() ) can get really expensive.
A bit OT, just out of interest: Do you know whether there is a good or common solution against this problem?

cheers Joe
Post Reply