The preprocessor and macros
#define, conditional compilation, header guards. The traps macros set and how to use them safely.
The preprocessor is a text-replacement step that runs before compilation. #include pastes in a file's contents and #define substitutes a value for a name.
Macro traps
#define SQ(x) x * x
SQ(a + 1) // expands to a + 1 * a + 1
#define SQ(x) ((x) * (x)) // wrap in parentheses
Pass i++ to a macro that uses its argument twice and it increments twice. Macros that calculate are safer rewritten as static inline functions.
Conditional compilation
#ifdef DEBUG
log_printf("adc=%u\n", adc);
#endif
Code is included or left out depending on board revision or debug build. Overused, nobody can tell which combination is really built, so gather the switches in one configuration header.
Header guards
They stop the same header being included twice and its definitions colliding.
#ifndef MOTOR_H
#define MOTOR_H
...
#endif