8

Well, there is no guarantee by the standard that inline functions are actually inlined; one must use macros to have 100 % guarantee. The compiler always decides which function is or is not inlined based on its own rules irrespective of the inline keyword.

Then when will the inline keyword actually have some effect to what the compiler does when using modern compilers such as the recent version of GCC?

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • 6
    Macros are not a 100% guarantee. A compiler is free to factor out duplicate code (from multiple expansions of a macro) into multiple calls to the same copy of the code (essentially a function call). – R.. GitHub STOP HELPING ICE Dec 14 '14 at 00:50
  • In C++ it's effective when you need to worry about [ODR](http://en.wikipedia.org/wiki/One_Definition_Rule)... probably similar in C. – user541686 Dec 14 '14 at 00:53
  • @R..: I don't know of any compilers that do that though, so to me they're effectively guarantees. – user541686 Dec 14 '14 at 00:54
  • 1
    @R..: Macros are always substituted at the usage site by the preprocessor. After that, they're subject to the same optimizations as any other code placed directly inside the function. – Ben Voigt Dec 14 '14 at 00:56
  • 2
    You should certainly review [Is `inline` without `static` or `extern` ever useful in C99?](http://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99), and you might review [`extern inline`](http://stackoverflow.com/questions/216510/extern-inline) too. Note that it is worth making even non-inline functions `static` whenever possible; the compiler may well optimize them into inline code if it makes sense, but it can only do that if it knows the function will not be called from outside the current source file, which means the function must be `static`. – Jonathan Leffler Dec 14 '14 at 00:59
  • 2
    @JonathanLeffler Small nitpick: The compiler does inline non-`static` functions, it just has to leave a copy for external callers around (increasing code size). Whether this affects inlining heuristics I do not know. There are other good reasons to make helper functions `static` though (less pollution of the global namespace, and hence the ability to use shorter, nicer names). –  Dec 14 '14 at 01:05
  • @delnan: I've not observed a compiler inlining non-static functions, but that doesn't mean it can't or doesn't happen. I wrote what I know. I think it is a good discipline to make everything static by default, only exposing it when you know something outside the current source file needs to use it. Yes, more convenient names can be a benefit, too, as long as you follow the discipline of using appropriately systematic (usually longer) names if you have to expose the function (you wouldn't be so gauche as to make a variable visible, would you?) to other code. Remember to update the header, too. – Jonathan Leffler Dec 14 '14 at 01:10

2 Answers2

4

It has a semantic effect. To simplify, a function marked inline may be defined multiple times in one program — though all definitions must be equivalent to each other — so presence of inline is required for correctness when including the function definition in headers (which is, in turn, makes the definition visible so the compiler can inline it without LTO).

Other than that, for inlining-the-optimization, "never" is a perfectly safe approximation. It probably has some effect in some compilers, but nothing worth losing sleep over, especially not without actual hard data. For example, in the following code, using Clang 3.0 or GCC 4.7, main contains the same code whether work is marked inline or not. The only difference is whether work remains as stand-alone function for other translation units to link to, or is removed.

void work(double *a, double *b) {
  if (*b > *a) *a = *b;
}

void maxArray(double* x, double* y) {
    for (int i = 0; i < 65536; i++) {
        //if (y[i] > x[i]) x[i] = y[i];
        work(x+i, y+i);
    }
}
  • 十1 for the one semantic effect, but you should elaborate on it a little. `inline` does not exempt you from the "one definition rule". There still must be exactly one external definition, and if it does not match the inline definition, the result is undefined. – R.. GitHub STOP HELPING ICE Dec 14 '14 at 01:05
  • @R.. Yes, I gloss over many details, some of which I'm probably not even aware of. I'll add in some weasel words. –  Dec 14 '14 at 01:07
  • 3
    The "one definition rule" is a C++ term, and C++ semantics of `inline` don't match those of C. C always needs one external definition, even if there's an inline definition in every translation unit, and *does* allow inline definitions that have different bodies (and it is unspecified which of those gets called). –  Dec 14 '14 at 01:11
  • 1
    @hvd: I don't think C always needs an external definition of an inline function. If you use a header to define the function as `static inline ...`, you won't get any linking errors as long as that header is used everywhere the function is used. – Jonathan Leffler Dec 14 '14 at 01:12
  • @JonathanLeffler You're right. What I said only applies to functions with external linkage, and I should have specified that. Functions with internal linkage have simpler rules. –  Dec 14 '14 at 01:13
  • @hvd: I 100% agree with you that "[f]unctions with internal linkage have simpler rules". To a first approximation, I'd say "always use `static inline` so you can understand it". – Jonathan Leffler Dec 14 '14 at 01:16
  • 1
    @JonathanLeffler: With `static`, `inline` is semantically a no-op, so the non-`static` case is the interesting one. On the other hand, I agree `static` is what you usually want. External inline semantics are too confusing, especially with the incompatible GNU semantics that are default in some GCC profiles. :( – R.. GitHub STOP HELPING ICE Dec 14 '14 at 01:21
1

If you want to control inlining, stick to whatever pragmas or attributes your compiler provides with which to control that behaviour. For example __attribute__((always_inline)) on GCC and similar compilers. As you've mentioned, the inline keyword is often ignored depending on optimization settings, etc.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469