Though C macros are so bad they give the whole term a bad name. You might as well write a sed script for “macro expansion” instead of what the preprocessor does.
I agree there's nothing particularly terrible about the preprocessor as such, if used tastefully. Especially if you compare it to other macro engines like maybe TeX, CPP strikes me as quite simple and clean.
Even newer languages like Haskell choose to adopt it after all.
That said, I'd be interested to hear about other solutions that are better. I guess Zig's comptime is a candidate, but I see that as only a superficial improvement (not a criticism - I can't think of anything it could do better).
But a macro system without understanding the AST is just shitty.