Inline functions vs Preprocessor macros

84,502

Solution 1

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.

Solution 2

First, the preprocessor macros are just "copy paste" in the code before the compilation. So there is no type checking, and some side effects can appear

For example, if you want to compare 2 values:

#define max(a,b) ((a<b)?b:a)

The side effects appear if you use max(a++,b++) for example (a or b will be incremented twice). Instead, use (for example)

inline int max( int a, int b) { return ((a<b)?b:a); }

Solution 3

The inline functions are expanded by the compiler where as the macros are expanded by the preprocessor which is a mere textual substitution.

Hence,

  • There is no type checking during macro invocation while type checking is done during function call.

  • Undesired results and inefficiency may occur during macro expansion due to reevaluation of arguments and order of operations. For example:

    #define MAX(a,b) ((a)>(b) ? (a) : (b))
    int i = 5, j = MAX(i++, 0);
    

    would result in

    int i = 5, j = ((i++)>(0) ? (i++) : (0));
    
  • The macro arguments are not evaluated before macro expansion

     #include <stdio.h>
     #define MUL(a, b) a*b
    
     int main()
     {
         // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
         printf("%d", MUL(2+3, 3+5));
         return 0;
     }
     // Output: 16
    
  • The return keyword cannot be used in macros to return values as in the case of functions.

  • Inline functions can be overloaded.

  • The tokens passed to macros can be concatenated using operator ## called Token-Pasting operator.

  • Macros are generally used for code reuse where as inline functions are used to eliminate the time overhead (excess time) during function call (avoiding a jump to a subroutine).

Solution 4

The key difference is type checking. The compiler will check whether what you pass as input values is of types that can be passed into the function. That's not true with preprocessor macros - they are expanded prior to any type checking and that can cause severe and hard to detect bugs.

Here are several other less obvious points outlined.

Solution 5

To add another difference to those already given: you can't step through a #define in the debugger, but you can step through an inline function.

Share:
84,502
Subodh
Author by

Subodh

Updated on February 04, 2022

Comments

  • Subodh
    Subodh over 2 years

    How does an inline function differ from a preprocessor macro?

  • Martin York
    Martin York almost 15 years
    Inline function are not always guaranteed to be inlined: Because the compiler will not inline if doing so will generate slower code etc. The compiler does a lot of analysis that the Engineer can not and does the correct thing.
  • LBushkin
    LBushkin almost 15 years
    I believe that recursive functions are another example where most compilers ignore inlining.
  • rzetterberg
    rzetterberg over 12 years
    Are there any important differences in C compared to C++ in this case?
  • dbrank0
    dbrank0 over 11 years
    One point not mentioned is that inlining can be influenced by compilation flags. For example, when you build for maximum speed (like GCC -O2/-O3) compiler will choose to inline many functions, but when you build for minimum size (-Os) if will typically inline functions called only once (or very small functions). With macros there is no such choice.
  • Hit's
    Hit's almost 10 years
    Macros can't cover with access specifier (like, private or protected) while inline functions are possible.
  • Nir Friedman
    Nir Friedman about 9 years
    There are directives supported by most compilers that can force an inline, regardless of compiler optimization level.
  • watashiSHUN
    watashiSHUN over 6 years
    Just want to add to your example that besides side effect, macro can also introduce extra work load, consider max(fibonacci(100), factorial(10000)) the larger one will get calculated twice :(
  • Jonathan Leffler
    Jonathan Leffler almost 6 years
    How much more fun do you get from #define TWO_N(n) 2 << n and then cout << CUBE(TWO_N(3 + 1)) << endl;? (It's better to end lines of output with endl than to begin them with it.)
  • ruach
    ruach over 5 years
    To prevent the macro function having unwanted side effects and allow the macro function to declare a temporary variable, GNU C provides statement expression (as an extension of the standard C), which is a compound statement enclosed in the parentheses () (e.g., ( { } ). For the details, please refer this [link]()
  • Admin
    Admin almost 4 years
    Everybody speaks about Type Checking but just you provided a real-world example, that's why I upvote this answer.
  • mike
    mike almost 4 years
    Just as a remark: The macro can be fixed to evaluate to the same number with brackets. However, it is still error prone, since you need to think about the absolute dumb subsitution and all cases during implementation.
  • Milan
    Milan almost 3 years
    @watashiSHUN Why would the larger one get calculated twice? Thanks in advance!
  • Milan
    Milan almost 3 years
    In the macro, Why will a or b be incremented twice? It's because the max(a++, b++) will be replaced with (a++ < b++) ? b++ : a++, correct? I guess that also answers my above question (in regards to @watashiSHUN 's comment). Thanks in advance!