Preprocessor — #define, args, token pasting - MarekBykowski/readme GitHub Wiki

// Object-like macro
#define MAX_DRONES  16
#define PI          3.14159f

// Function-like macro — parenthesise everything!
#define MAX(a, b)   ((a) > (b) ? (a) : (b))  // safe
#define SQUARE(x)   ((x) * (x))               // safe
#define BAD(x)      x * x                     // unsafe: BAD(1+2) → 1+2*1+2 = 5!

// Stringification — # turns token into string literal
#define STRINGIFY(x)   #x
STRINGIFY(hello)  →  "hello"

// Stringification — stringify not name but value
#define VERSION  3
#define TOSTRING(x)  STRINGIFY(x)
#define STRINGIFY(x) #x
TOSTRING(VERSION) -> "3"
printf("Version: " TOSTRING(VERSION));  // "Version: 3"


// Token pasting — ## concatenates tokens
#define REG(n)   reg_##n
REG(status)  →  reg_status

// Conditional compilation
#ifdef DEBUG
    #define LOG(msg)  printf("[DBG] %s\n", msg)
#else
    #define LOG(msg)  ((void)0)   // compiles to nothing
#endif

// X-macro pattern — define list once, generate multiple things
#define STATES(X)  X(IDLE) X(ARMED) X(FLYING) X(FAULT)

typedef enum {
#define ENTRY(n) STATE_##n,
    STATES(ENTRY)
#undef ENTRY
} state_t;

static const char *state_names[] = {
#define ENTRY(n) [STATE_##n] = #n,
    STATES(ENTRY)
#undef ENTRY
};