Earlier quoted context omitted.
Anytime macros are used for metaprogramming, it's time to reach for a more powerful language.
You might as well have written that "any time you're reaching for C, it's time to reach for a more powerful language". But if -sadly- you must use C, metaprogramming using macros is not a terrible thing.
It is a terrible thing. It's possible to do without them, and you'll like your code better. Your symbolic debugger and syntax directed editor will work properly. The poor schlub who has to fix the bugs in your code after you leave will be grateful. Your spouse will be happy and your children will prosper.
For example,
#define foo(x) ((x) + 1)
replace with: int foo(int x) { return x + 1; }
The compiler will inline it for you. There's no penalty. #define FOO 3
Replace with: enum { FOO = 3 };
or: const int FOO = 3;
Replace: #if FOO == 3
bar();
#endif
with: if (FOO == 3) bar();
The optimizer will delete bar() if FOO is a manifest constant that is not 3.