gordon@hermod.cs.cornell.edu (Jeffrey Adam Gordon) (05/04/90)
Thanks to all who have replied and posted. I'm getting a lot of
repeated suggestions at this point so here's a summary (the first is
the one I have chosen to use. I prefer it because it does not leave
any dead code (except a semicolon) lying around and does not rely on a
smart compiler optimizing things away.
-----------------------------------------------------------------------
The most common thing I've seen goes something like:
#ifdef DEBUG
#define DPRINT(x) printf x
#else
#define DPRINT(x)
#endif
then in your code do:
DPRINT(("stuff %d\n", abc));
note that the double paren's are crucial, it makes 1 arg for the
preprocessor, which either comes after printf or is discarded.
----------------------------------------------------------------------
another way would be to use something like this:
#define DEBUG 0
...
if (DEBUG) printf(....);
...
if your compiler is worth anything, it should optimize out the printf if
DEBUG is 0. if you set DEBUG to 1 at the compile line, then the printf's
will be in place, and the compiler should still optimize out the "if" since
it is always true.
-----------------------------------------------------------------------
#ifdef DODEBUG
# define DEBUG printf
#else
# define DEBUG (void)
#endif DODEBUG
Now when you say
DEBUG(format, var1, var2, var3);
it expands to one of
printf(format, var1, var2, var3);
or
(void)(format, var1, var2, var3);
Both of which are legal statements; the first is a function call, the
second is a parenthesized comma-expression. Any reasonable compiler will
detect that the second form can be completely optimized out, since the
value is never used (in fact, it's explicitly thrown away).
One effect of this, which may be considered either a drawback or an
advantage depending on your point of view, is that if you accidentally
use an operation that has side effects in a DEBUG statement, that
operation will be executed regardless of the definintion of DODEBUG; the
compiler is obligated not to eliminate side-effected sub-expressions from
the comma-expression. On the other hand, side effects should still be
avoided, because the *order* of evaluation may differ for function param
lists and comma-exprs.
-----------------------------------------------------------------------
>
#define DEBUG1(x) printf(x)
#define DEBUG2(x,y) printf(x,y)
#define DEBUG3(x,y,z) printf(x,y,z)
etc. That's the best I've seen so far. It's ugly, and requires knowing lots
of names, but it works.
-----------------------------------------------------------------------
Some solutions also had a debug level but this was more than I needed.
Thanks all.
- Jeff
yedinak@motcid.UUCP (Mark A. Yedinak) (05/07/90)
gordon@hermod.cs.cornell.edu (Jeffrey Adam Gordon) writes: : Thanks to all who have replied and posted. I'm getting a lot of : repeated suggestions at this point so here's a summary (the first is : the one I have chosen to use. I prefer it because it does not leave : any dead code (except a semicolon) lying around and does not rely on a : smart compiler optimizing things away. : Some solutions also had a debug level but this was more than I needed. I have been following the thread concerning the debug mechanisms, and have decided to include my variation. It is primarily used on UNIX systems, and uses environment variables to define the level of debugs statements which will be selected. Again, all the debug statements can be compiled out of the code simply by undefining the #define PROG_DEBUG. Following is the macro definition and an sample program. |--------------------------- Cut Here -----------------------------------------| #include <stdio.h> #define PROG_MAIN /* Defined in the file containing main () */ /******************************************************************************* * * Macro: PROG_DEBUG * Purpose: The following definition is used to define a in line * debug mechanism which can be compiled out of the code. * In addition, when compiled in, it can be switched off * using an environment variable. If the environment * variable is set, the debug code is executed. The macro * will also allow settable modes of debug statements. The * value of the environment variable will be 'AND' with * the coded debug level, if the level was selected, the * statements will be executed. A debug macro can be forced * to be displayed simply by setting the code level to 255. * Likewise, if the envrionment variable is set to 255, all * debug statements will be executed. * * Range of ENV_DEBUG is 0 <= ENV_DEBUG <= 255 * * This allows the in line debug code to be accessed easily. * Arguments: L The coded debug level. * S The c statements desired in the debug code. These * can be any valid c constructs. I am not sure if * there is a maximium length for the lines, however * I have been able to place a significant amount of * code in a single debug macro. * Return: None * Author: Mark A. Yedinak * *******************************************************************************/ #ifdef PROG_DEBUG # define init_debug debug_flag = (char) (atoi \ (getenv ("ENV_DEBUG")==NULL\ ?"":getenv ("ENV_DEBUG"))) # # define debug(L,S) if (debug_flag & (L)) { S } # ifdef PROG_MAIN extern char *getenv (); char debug_flag; FILE *dbg_fp; # else extern char debug_flag; extern FILE *dbg_fp; # endif #else # define init_debug /**/ # define debug(L,S) /**/ #endif main () { init_debug; debug (1, dbg_fp = stdout; printf ("Executing Level 1 debug code\n"); fflush (dbg_fp); ); debug (2, dbg_fp = stdout; printf ("Executing Level 2 debug code\n"); fflush (dbg_fp); ); debug (255, dbg_fp = stdout; printf ("Forced Execution of debug code\n"); fflush (dbg_fp); ); printf ("Executing in-line code\n"); } |--------------------------- Cut Here -----------------------------------------| -- Mark A. Yedinak - uunet!motcid!yedinak * "Don't take life too Motorola - General Systems Sector * seriously, you will 3205 Wilke Road, Arlington Heights, IL 60004 * never get out of it 708-632-2874 (Usual Disclaimers) * ALIVE!"