Ground Embedded KO Subscribe

Notes / C Language

The preprocessor and macros

#define, conditional compilation, header guards. The traps macros set and how to use them safely.

GROUND EMBEDDED · NOTEC Language 11Preprocessor and macros 1volatile uint32_t *ODR 2 = (uint32_t*)0x40020014; 3*ODR |= (1u << 5); 4while (1) { 5 if (flag) toggle(); 6}

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

SQ(a + 1)Text substitutiona + 1 * a + 1multiplication firstWrong value
A macro substitutes text as it is. Without parentheses the order of calculation changes.
#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

#include "motor.h"first timeMOTOR_H defined#include "motor.h"second timeSkipped by #ifndef
Even if the same header is included twice, the whole content is skipped the second time.

They stop the same header being included twice and its definitions colliding.

#ifndef MOTOR_H
#define MOTOR_H
...
#endif
FREE PDFGet the 3 free ebooksIf you want to keep reading this topic as one book: BLDC motor control, serial communication and sensors at book length. PDFs are in Korean.Get them free →