CHAPTER 8 - The Preprocessor ============================ Basic directives: define and include ------------------------------------ #define identifier string substitutes identifier with string, but not inside "..." #undef identifier undefines a macro #define PI 3.14159 #define C 299792.458 /* speed of light */ #define EOF (-1) #define MAXINT 2147483647 can continue to the next line by ending the current line with a \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include #include "mydef.h" ============================================================= Macros with parameters ---------------------- #define identifier( identifier,...,identifier ) string Example: #define SQ(x) ((x) * (x)) SQ(7 + w) expands to ((7 + w) * (7 + w)) SQ(SQ(*p)) expands to ((((*p) * (*p))) * (((*p) * (*p)))) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bad declarations ---------------- #define SQ(x) x * x SQ(a + b) expands to a + b * a + b #define SQ(x) (x) * (x) 4 / SQ (2) expands to 4 / (2) * (2) #define SQ (x) ((x) * (x)) SQ(7) expands to (x) ((x) * (x)) (7) #define SQ(x) ((x) * (x)); /* error */ if (x == 2) x = SQ(y); else ++x; ============================================================= Macro nesting ------------- #define min(x, y) (((x) < (y)) ? (x) : (y)) m = min(u, v) expands to m = (((u) < (v)) ? (u) : (v)) #define min4(a, b, c, d) min(min(a,b), min(c,d)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define SQ(x) ((x) * (x)) #define CUBE(x) (SQ(x) * (x)) #define F_POW(x) sqrt(sqrt(CUBE(x)))) /* fractional power: 3/4 */ ============================================================= operating the preprocessor only ------------------------------- gcc -E file.c ============================================================= conditional compilation ----------------------- #if constant_integral_expression #ifdef identifier #ifndef identifier if expr is true will compile the lines till: #endif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #if defined(HP9000) || defined(SUN4) && !defined(VAX) ...... /* machine_dependent code */ #endif #if defined(identifier) is equivalent to #ifdef identifier ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define DEBUG #ifdef DEBUG printf("debug: a = %d\n", a); #endif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include "everything.h" #undef PIE #define PIE "I like apple." ....... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ commenting out a code fragment ------------------------------ statement #if 0 more statements #endif and still more statements ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #elif constant_interal_expression #else #endif ============================================================= A sample of ready-made macros, functions and typedefs ------------------------------------------------------ in stddef.h ----------- (possible implementation:) typedef unsigned size_t; #define NULL ((void *) 0) in stdio.h ---------- getchar(), putchar(c) in ctype.h ---------- isalpha(c), isupper(c), isdigit(c): all get int and return int predefined (no need to include a special file) ---------------------------------------------- always there, cannot be undefined __DATE__ string __FILE__ string __LINE__ int __TIME__ string __STDC__ non-zero integer if the implementation follows ANSI C /* assert.h */ #include #include /* for abort() */ #if defined(NDEBUG) #define assert(ignore) ((void) 0) /* ignore it */ #else #define assert(expr) \ if (!(expr)) { \ printf("\n%s%s\n%s%s\n%s%d\n\n", \ "Assertion failed: ", #expr, \ "in file ", __FILE__, \ "at line ", __LINE__); \ abort(); \ } #endif