#define can also be given arguments which are used in its replacement. The definitions are then called macros. Macros work rather like functions, but with the following minor differences.
Macros are full of traps for the unwary programmer. In particular the textual substitution means that arithmetic expressions are liable to be corrupted by the order of evaluation rules.
Here is an example of a macro which won't work.
#define DOUBLE(x) x+x
Now if we have a statement
a = DOUBLE(b) * c;
This will be expanded to
a = b+b * c;
And since * has a higher priority than +, the compiler will treat it as.
a = b + (b * c);
The problem can be solved using a more robust definition of DOUBLE
#define DOUBLE(x) (x+x)
Here the brackets around the definition force the expression to be evaluated before any surrounding operators are applied. This should make the macro more reliable.
In general it is better to write a C function than risk using a macro.