The simplest form of macro replacement is to define a manifest constant, as in

#define ARRSIZE 100
int array[ARRSIZE];

This defines a function-like macro that multiplies a variable by 10 and stores the new value:

#define TIMES10(A) ((A) *= 10)

double b = 34;
int c = 23;

TIMES10(b);   // good: ((b) *= 10);
TIMES10(c);   // good: ((c) *= 10);
TIMES10(5);   // bad:  ((5) *= 10);

The replacement is done before any other interpretation of the program text. In the first call to TIMES10 the name A from the definition is replaced by b and the so expanded text is then put in place of the call. Note that this definition of TIMES10 is not equivalent to

#define TIMES10(A) ((A) = (A) * 10)

because this could evaluate the replacement of A, twice, which can have unwanted side effects.

The following defines a function-like macro which value is the maximum of its arguments. It has the advantages of working for any compatible types of the arguments and of generating in-line code without the overhead of function calling. It has the disadvantages of evaluating one or the other of its arguments a second time (including side effects) and of generating more code than a function if invoked several times.

#define max(a, b) ((a) > (b) ? (a) : (b))

int maxVal = max(11, 43);              /* 43 */
int maxValExpr = max(11 + 36, 51 - 7); /* 47 */

/* Should not be done, due to expression being evaluated twice */
int j = 0, i = 0;
int sideEffect = max(++i, ++j);       /* i == 4 */

Because of this, such macros that evaluate their arguments multiple times are usually avoided in production code. Since C11 there is the _Generic feature that allows to avoid such multiple invocations.

The abundant parentheses in the macro expansions (right hand side of the definition) ensure that the arguments and the resulting expression are bound properly and fit well into the context in which the macro is called.