Preprocessor
Preprocessor: program that processes source code before compilation
File Inclusion
#include "filename" // use when the file exists locally
#include <filename> // use for the standard C libraries
Macro Substitution
#define name replacement_text
name will be replaced by replacement_text like how you assign values to variable
A long definition can be written by using a \ at the end of the line
Substitution doesn’t work for quoted string
#define forever for (;;) // infinite loop
#define max(a, b) ((a) > (b) ? (a) : (b))
/* looks like function invocation, but a and b will be replaced by values, e.g., x = max((p + q), (r + s)); will be replaced by x = ((p + q) > (r + s) ? (p + q) : (r + s)); */
This macro will work fine as long as the arguments are treated consistently. However, the problem is that the expression evaluate twice; it will gives wrong values if we use increment.
x = max(i++, j++);
In this case, it will be incremented twice
Consider the macro
#define square(x) x * x
When we pass z + 1 as the parameter, the macro would return z + 1 * z + 1 = z + z + 1 = 2 * z + 1 rather than (z + 1) * (z + 1)
So, to get the intended behavior, we must use extra parentheses
#define square(x) (x) * (x)
#undef tells the processsor to undefine the macro
#undef getchar
Formal parameters are not replaced with quoted string. However, if # is present in the replacement text, then the combination will be exxpanded into quoted string
Consider
#define dprint(exp) printf(#exp " = &g\n", exp)
The invocation of dprint(x/y) will be
printf("x/y = &g\n", x/y);
Conditional Inclusion
We can use conditional statement in preprocessor with #if
Consider we have a hdr.h file
If we want to make sure the file is included, we can use
#if !define(HDR)
#define HDR
// contents
#endif