Inline Functions VS Preprocessor Macros

Inline functions vs Preprocessor macros

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.

inline function vs macro function

Inline replaces a call to a function with the body of the function, however, inline is just a request to the compiler that could be ignored (you could still pass some flags to the compiler to force inline or use always_inline attribute with gcc).

A macro on the other hand, is expanded by the preprocessor before compilation, so it's just like text substitution, also macros are not type checked, inline functions are. There's a comparison in the wiki.

For the sake of completeness, you could still have some kind of type safety with macros, using gcc's __typeof__ for example, the following generate almost identical code and both cause warnings if used with the wrong types:

#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })

__attribute__((always_inline)) int max(int a, int b) {
return (a > b ? a : b);
}

Note: sometimes typeless macros are just what's needed, for example, have a look at how uthash uses macros to make any C structure hashable without resorting to casts.

Macro vs Inline

  1. Inline functions are functions. They just have an additional inline attribute to hint the compiler that it might be good to inline those functions as an optimization. It's been said that compilers might not even listen to that. From your point of view, inline functions are 100% equal to functions. It's an optimization technique for the compiler.

    Macros are code-generation templates. You define a template such as #define ADD_ONE(x) x = x + 1;, and the preprocessor (not the compiler) will simply replace those strings by your template strings. Macros means "string-substitution" (with a few rules).
  2. Macros should be your last recourse. Use them when you would otherwise repeat code that doesn't need to be repeated.
  3. True and false. Macros are simply string-substitution. So the code is inline. Inline functions may not be inline (see #1), therefore they are not "also" inline. I should add that inline means that there is no function call made while running that code.

What's the difference in practice between inline and #define?

#define is a preprocessor tool and has macro semantics. Consider this, if max(a,b) is a macro defined as

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

Ex 1:

val = max(100, GetBloodSample(BS_LDL)) would spill extra innocent blood, because the function will actually be called twice. This might mean significant performance difference for real applications.

Ex 2:

val = max(3, schroedingerCat.GetNumPaws())
This demonstrates a serious difference in program logic, because this can unexpectedly return a number which is less than 3 - something the user would not expect.

Ex 3:

val = max(x, y++) might increment y more than one time.


With inline functions, none of these will happen.

The main reason is that macro concept targets transparency of implementation (textual code replace) and inline targets proper language concepts, making the invocation semantics more transparent to the user.

Inline functions vs Preprocessor macros

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.


Related Topics



Leave a reply



Submit