Earlier in the course we saw that the C pre-processor performs textual substitution. The preprocessor can do more than this, it can conditionally compile (or ignore) portions of code, and it can expand macros to behave like functions (with no compiler checking of parameter and return types). Many standard library functions are implemented as macros. A useful example is the assert function, declared in assert.h. If your code contains a statement such as:
assert(n > 0);...stating some condition you intend to be true at all times, then if the condition is ever false your program exits, prints the file and line number, plus stating that the condition failed.
You can create your own macros. The following example defines DD1 to print the file, line number, and then a formatted string (argument a) that uses an argument (b). This version of DD1 is defined only if DEBUG is defined, otherwise DD1 becomes an empty macro (resulting in an empty, but legal, statement). When compiling you can make sure DEBUG is defined by including -DDEBUG in the gcc command (e.g. gcc -DDEBUG myprog.c
/* experiment a bit with macros */ #include <stdio.h> #ifdef DEBUG #define DD1(a,b) printf("%s: %d " a, __FILE__, __LINE__, b); #else #define DD1(a,b) #endif int main() { int i= 5; #ifdef DEBUG printf("Debugging on!\n"); #else printf("Debugging off!\n"); #endif DD1("The value of i is %d\n", i); return 0; }If the replacement list for a macro contains an operator (e.g. ``*''), you should enclose the list with parentheses. Similarly, if the arguments for the macro are expressions, they should be enclosed in parentheses (See K.N. King, chapter 14). Here's an example
#ifdef CARELESS #define MAX(x,y) x>y?x:y #else #define MAX(x,y) ((x)>(y)?(x):(y)) #endifWith CARELESS defined, you might get surprising results from, say 3 * MAX(2,3).
Next Monday's tutorial will give you more details about preprocessor and conditional compilation.