> 1. Global scope only.
So are functions, by that rationale. If you want to control scope of variables, pass in macro parameters.
> 2. Unexpected results rather than error messages
When have min() or max() produced unexpected results rather than error messages? They're macros, you know.
> Every compiler I've used, including GCC, won't warn about if an int is compared to unsigned.
-Wconversion
> 5. can't take the address
You can't take the address of a struct definition or a typedef, either. Macros are not replacements for functions; they're code generators.
> 6. worst, substituted value need not even be legal in the context the #define is created because it is evaluated at each point it is referenced allowing to another evil problem of being able to reference objects that are not declared yet.
I don't even... You do know that, following the preprocessing phase, the compiler actually checks the generated code for legality, right? And since when is forward referencing evil?