__debug Statement
Two versions of a program are typically written, a debug version and a release version. The debug version contains extra code to do things like extra checking, printing out the values of variables, etc. Unfortunately, C/C++ provides no language support for this, it all must be done with the preprocessor.
The obvious way to do it is bracket the code with:
#ifdef DEBUG ... #else ... #endif
but it winds up looking clumsy. Various attempts are made to clean up the look by using macros, but macros run afoul of:
- poor support for multiline macros
- functions with variable numbers of arguments like printf() are problematic
- whether {} or () are used is problematic and inconsistent.
The solution is to build the syntax right into the language. Hence the debug statement:
debug_statement ::= "__debug" ["(" expression ")"] statement ["else" statement]
Debug statements are compiled in when the -D switch is thrown, else they are simply parsed and thrown away without doing a semantic check.
The debug statement takes on several forms:
__debug printf("Blah, blah\n");
will only compile in the printf if -D is thrown. Alternatively,
__debug { printf("Blah, blah\n"); }
will do the same thing. A debug statement without a (expression) and without { } does not introduce a new scope,
__debug int i = 7; __debug printf("i = %d\n", i);
whereas:
__debug { int i = 7; } __debug printf("i = %d\n", i); // error, i undefined
An else clause can be added:
__debug { printf("Debug version\n"); } else { printf("Release version\n"); }
The debugging code can also be switched on and off at runtime with:
__debug (print_vars) { printf("Debug: vars = %d\n", vars); } else { printf("Release version\n"); }
But if the -D switch is not thrown, only the else clause gets compiled.
Debug Declarations
Declarations can also be subject to the -D compiler switch:
__debug static int x; // compile only in debug mode
which in legacy compilers would be:
#ifdef DEBUG static int x; // compile only in debug mode #endif