Macros are used in C/C++ to #define textual replacements that can contain (almost) any C code. These include macros for important constants or even functional code. How do macros work? The preprocessor will replace any macro calls with the code itself.

Using macros to define constants is a fairly common practice. Using them to define functions in practice generally end up obfuscating otherwise clean code.

Some key ideas for function-like macros:

  • Macros should not change control flows in any surprising ways.
  • Any function-like macros should syntactically behave like function calls.
  • Whenever possible, use an inline function instead of a functional macro. This achieves a similar purpose but is easier to understand.

Note that because of the way the pre-processor works, macros typically don’t actually obey C syntactical rules. For example:

#define SQUARE(x) x * x
int result = SQUARE(2 + 3);
assert(result == (2 + 3 * 2 + 3)); // true
assert(result != 25); // true

So it doesn’t properly evaluate the operators. A correct function macro is:

#define SQUARE(x) ((x) * (x))