Day 4: The C Pre-Processor, Continued [Mostly Macros] Admin * What do you want to do next week? * Code mostly in Examples/CPP, Examples/Min1, and Examples/Min2 Overview * CPP Review * Macros: Review * An Extended Example: Code Templates * Macros vs. Functions, Revisited * Multi-Line and Multi-Step Macros * Testing and Experiments CPP Review * Textual processing of C programs. * Three basic features * #include * Conditional text #ifdef #if #else #endif * Macros #define MACRO(PARAMS) REPLACEMENT Macros Review * See above * #PARAM => the parameter as a string * THING ## OTHER => concatenate Extended Example (from last class): Code Templates * I.e., One technique for type-independent coding in C. * Start with code for one type (e.g., integer min). We note that if we wanted to make it work for another type, we would change * Type (return type, type of array, type of variable) * Prefix (function name) * Comparator * What should we do next? * Strategy one (from last time) Put the template in a file #define TYPE int #define PREFIX(FUNC) i ## FUNC #define LT(X,Y) (X < Y) #include "template.c" * Observation: Maybe the comparator should be a parameter to the min function (which we might then call "optimum", even if I haven't done so). * Are there other strategies that some people might find less ugly (or more ugly)? * Write a code generator printf ("%s %smin(%s data[], int len)\n", type, prefix, type); * Write a macro that generates the code #define DECLARE_MAX(TYPE, PREFIX) TYPE PREFIX ## max (TYPE ...) DECLARE_MAX(int, i) DECLARE_MAX(char *, s) DECLARE_MAX(float, f) * Use the most famous macro processor for C, C++ Macros v. Functions, Revisited * Why macros might be better than functions * SPEED. No function call, so less overhead. * Special capabilities (#FOO FOO ## BAR) * Speed can be addressed in other ways * inline __inline__ * Advantage of function: Recursive, parameter * Advantage of macro: Inlined when appropriate; code reduced * Why not macros? * Can be hard to read their declarations. (The macro "calls" look much like function calls.) * Can lead to unexpected behavior if params reused. #define SQUARE(X) X*X i = 3; printf ("%d\n", SQUARE(i++)); printf ("%d\n", i); => i = 3 printf ("%d\n", SQUARE(i++ * i++)); printf ("%d\n", i); // 5 printf ("%d\n", SQUARE(i+1)); // i+1*i+1 * Fixing it: Parentheses help a little bit #define SQUARE(X) ((X)*(X)) * Fixing it: Multiple steps #define SQUARE(X) Macros for Testing and Experiments Useful to have an EXPT macro that (a) prints out a line (b) executes the line #define EXPT(CODE) printf ("%s\n", CODE); CODE Bigger Macros (Multiple Lines, Multiple Steps)