Preprocessor macros are just substitution patterns applied to your code. They can be used almost anywhere in your code because they are replaced with their expansions before any compilation starts.
Inline functions are actual functions whose body is directly injected into their call site. They can only be used where a function call is appropriate.
Now, as far as using macros vs. inline functions in a function-like context, be advised that:
- Macros are not type safe, and can be expanded regardless of whether they are syntatically correct - the compile phase will report errors resulting from macro expansion problems.
- Macros can be used in context where you don't expect, resulting in problems
- Macros are more flexible, in that they can expand other macros - whereas inline functions don't necessarily do this.
- Macros can result in side effects because of their expansion, since the input expressions are copied wherever they appear in the pattern.
- Inline function are not always guaranteed to be inlined - some compilers only do this in release builds, or when they are specifically configured to do so. Also, in some cases inlining may not be possible.
- Inline functions can provide scope for variables (particularly static ones), preprocessor macros can only do this in code blocks {...}, and static variables will not behave exactly the same way.