3

To my understanding the difference between a macro and a function is, that a macro-call will be replaced by the instruction in the definition, and a function does the whole push, branch and pop -thing. Is this right, or have I understand something wrong?

Additionally, if this is right, it would mean, that macros would take more space, but would be faster (because of the lack of the push, branch and pop instructions), wouldn't it?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
DAHANS
  • 41
  • 4
  • 4
    Macros is just text copying. The preprocessor just replaces the macro with the aliased text you supplied. – 101010 May 27 '14 at 21:18
  • related to http://stackoverflow.com/questions/5226803/inline-function-v-macro-in-c-whats-the-overhead-memory-speed – uchar May 27 '14 at 21:28

4 Answers4

7

What you are wrote about the performance implications is correct if the C compiler is not optimizing. But optimizing compilers can inline functions just as if they were macros, so an inlined function call runs at the same speed as a macro, and there is no pushing/popping overhead. To trigger inlining, enable optimization in your compiler settings (e.g. gcc -O2), and put your functions to the .h file as static inline.

Please note that sometimes inlining/macros is faster, sometimes a real function call is faster, depending on the code and the compiler. If the function body is very short (and most of it will be optimized away), usually inlining is faster than a function call.

Another important difference that macros can take arguments of different types, and the macro definition can make sense for multiple types (but the compiler won't do type checking for you, so you may get undesired behavior or a cryptic error message if you use a macro with the wrong argument type). This polymorphism is hard to mimic with functions in C (but easy in C++ with function overloading and function templates).

pts
  • 80,836
  • 20
  • 110
  • 183
  • And the inlining would be faster? – DAHANS May 27 '14 at 21:21
  • 1
    @DAHANS: Faster than what? – Dietrich Epp May 27 '14 at 21:22
  • 1
    *so an inlined function call runs at the same speed as a macro, and there is pushing/popping overhead* I think you wanted to say *and there is **no** pushing/popping...* – Filipe Gonçalves May 27 '14 at 21:26
  • I've updated my answer about the speed implications of inlining. – pts May 27 '14 at 21:27
  • @FilipeGonçalves: Done, added the *no*. – pts May 27 '14 at 21:28
  • Why `static`? All that means is that you cannot use the function in a header (e.g. in a template or in another inline). – James Kanze May 27 '14 at 21:42
  • 3
    And of course, one of the most important differences between macros and inline functions is that it is so easy to inadvertently evaluate the argument twice, or to mess up precedence if the argument is a complex expression. There is no reason ever to prefer a macro over an inline function. (There are other reasons to occasionally use macros, of course. `__LINE__` and `__FILE__` will only work in a macro, for example.) – James Kanze May 27 '14 at 21:45
  • @JamesKanze I've come across many compilers that are buggy w.r.t. inlining: if you have an `inline` function in the header but the compiler decides not to actually inline it, then linking fails with multiple definition errors. So, he adds the `static` because it has no downside, but it placates these buggy compilers. I don't follow what you mean about "cannot use the function in a header", we are talking about free functions declared `inline` in headers. – M.M May 27 '14 at 22:23
  • @MattMcNabb When? When I first started C++, the semantics of `inline` weren't that clear, and compilers did have trouble with local statics in an inlined function. Today, however... any compiler which can handle templates should have no problems with `inline`, and all the static does is introduce undefined behavior. – James Kanze May 28 '14 at 08:28
  • Please note that the behavior of `inline` is different between C and C++. In C `static inline` is needed to prevent the occasional duplicate symbol errors, in C++ `inline` and `static inline` are both fine. – pts May 28 '14 at 10:13
  • @JamesKanze explain how it introduces UB? – M.M May 28 '14 at 11:36
  • I thought I already did. If you use the function elsewhere in a header, then you violate the one definition rule at the point of use. – James Kanze May 28 '14 at 13:01
  • Perhaps an example would be best. In the header `static inline int k() { return 42; } struct C { int i; C() : i( k() ) {} };`. If the `inline` is not `static`, this is perfectly legal and well defined. If the `inline` is `static`, it is a violation of the ODR, resulting in undefined behavior. – James Kanze May 28 '14 at 13:14
7

This might have been right in the 1980s, but modern compilers are much better.

Functions don't always push and pop the stack, especially if they're leaf functions or have tail calls. Also, functions are often inlined, and can be inlined even if they are defined in other translation units (this is called link-time optimization).

But you're right that in general, when optimizations are turned off, a macro be inlined and a function won't be inlined. Either version may take more space, it depends on the particulars of the macro/function.

A function uses space in two ways: the body uses space, and the function call uses space. If the function body is very small, it may actually save space to inline it.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
2

Yes your understanding is right. But you should also note that, no type checking in macro and it can lead to side effect. You should also be very careful in parenthesizing macros.

haccks
  • 104,019
  • 25
  • 176
  • 264
1

Your understanding is half correct. The point is that macros are resolved before compilation. You should think of them as sophisticated text replacement tools (that's oversimplifying it, but is mostly what it comes down to).

So the difference is when in the build process your code is used.

This is orthogonal to the question of what the compiler really does with it when it creates the final binary code. It is more or less free to do whatever it thinks is correct to produce the intended behaviour. In C++, you can only hint at your preference with the inline keyword. The compiler is free to ignore that hint.

Again, this is orthogonal to the whole preprocessor business. Nothing stops you from writing macros which result in C++ code using the inline keyword, after all. Likewise, nobody stops you from writing macros which result in a lot of recursive C++ functions which the compiler will probably not be able to inline even if wanted to do.

The conclusion is that your question is wrong. It's a general question of having binaries with a lot of inlined functions vs. binaries with a lot of real function calls. Macros are just one technique you can use to influence the tradeoff in one way or the other, and you will ask yourself the same general question without macros.

The assumption that inlining a function will always trade space for speed is wrong. Inlining the wrong (i.e. too big) functions will even have a negative impact on speed. As is always the case with such opimisations, do not guess but measure.

You should read the FAQ on this: "Do inline functions improve performance?"

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62