They are the standard way to produce include guards, and other compile-time configurations (e.g. different code paths for Windows vs. Linux), usually paired with #if clauses.
What many people in the C world do is use it to make confusing function-like macros, which I do not recommend. Macros affect everything globally and replace text before the compiler actually looks at it, and can make debugging hell.
For simple constants, use const types instead of #define. And just use functions instead of function-like macros.
you can also use them to force inline code (one reason to use a macro function, but this should be an extremely rare thing where your over-ride of the compiler was actually better).
Personally I dislike macro functions so much that I would rather put the routine in a standalone file and #include it where it needs to be than #define macro it. They are that bad.