The Preprocessor
Note: All the programs mentioned in this lecture are in:/home/cs352/SUMMER02/lecture16progs/
PREPROCESSOR DIRECTIVES - Preprocessor directives: Lines that begin with # - The effect of a directive starts at its place, and continues until the end of the file or until it's negated. - #include - We've already seen and used, like: #include <stdio.h> #include <stdlib.h> #include "tree.h" - The include line gets replaced by the contents of the given file. - If the form is "file.h" then preprocessor first looks at the current directory to find file.h If it's like <file.h> then search is done at a system specific directory(such as /usr/include, ...) - Typically we can put prototypes of our functions, macro definitions, type definitions, etc. in a .h file, and include it in our program. - #define - General form is: #define identifier token-string - Ex: #define PI 3.14159 #define TRUE 1 (The preprocessor replaces every occurence of PI, and TRUE in the rest of the program, except in quoted strings, with the given token string.) - A long definition can continue the next line by putting \ at the end. - Macro definitions - General form is: #define identifier(identifier, ..., identifier) token-string - Ex: see macros.c - Common mistake: to put ; at the end.(; is interpreted as part of the token string then.) - Frequently used to replace functions.(more efficient) see fmacro.c - #undef identifier will make the previous definition of a macro forgotten. - see useqsort.c (the usage of directives, and functions as arguments to functions. - Common macros(that are already defined in the libraries): - getchar(), putchar() in stdio.h - macros operating on characters like isalpha(c), isupper(c), ... defined in ctype.h - assert(), in the standard header file assert.h to ensure the value of an expr is what you expect. see assert.c - Conditional Compilation - Preprocessor has directives for conditional compilation. - Each directive of the general form: #if const-int-expr (in order for cond. comp. expr. must be true) #ifdef identifier (identifier must bedefined prev, i.e. in #define) #ifndef identifier (identifier must not be defined previously) provides cond. compilation until #endif - Each of the #if directives can also be followed by #elif const-int-expr (for doing else if ....) #else (for doing else ....) followed by #endif - Why useful? If a big project and want to define constants, need to check if define already, if necc.. #undef For portability(if writing machine dependent code, might check the defined constants and stuff..) Debugging, error messages, etc.. - see moremacro.c