Instead of answering "what does it do?", I'm answering "how do I make it do what I want?" There are 5 kinds of inlining, all available in GNU C89, standard C99, and C++. MSVC has some of them (note that I haven't tested the MSVC code)
always inline, unless the address is taken
Add __attribute__((always_inline))
to any declaration, then use one of the
below cases to handle the possibility of its address being taken.
You should probably never use this, unless you need its semantics (e.g. to affect the assembly in a certain way, or to use alloca
). The compiler usually knows better than you whether it's worth it.
MSVC has __forceinline
which appears mostly the same, but apparently it refuses to inline in quite a few common circumstances (e.g. when optimization is off) where other compilers manage just fine.
inline and emit a weak symbol (like C++, aka "just make it work")
__attribute__((weak))
void foo(void);
inline void foo(void) { ... }
Note that this leaves a bunch of copies of the same code lying around, and the linker picks one arbitrarily.
MSVC doesn't appear to have an exact equivalent in C mode, although there are a couple of similar things. __declspec(selectany)
appears to be talking about data only, so might not apply to functions? There is also linker support for weak aliases, but does that work here?
inline, but never emit any symbol (leaving external references)
__attribute__((gnu_inline))
extern inline void foo(void) { ... }
MSVC's __declspec(dllimport)
, combined with an actual definition (otherwise unusual), supposedly does this.
emit always (for one TU, to resolve the preceding)
The hinted version emits a weak symbol in C++, but a strong symbol in either dialect of C:
void foo(void);
inline void foo(void) { ... }
Or you can do it without the hint, which emits a strong symbol in both languages:
void foo(void) { ... }
Generally, you know what language your TU is when you're providing the definitions, and probably don't need much inlining.
MSVC's __declspec(dllexport)
supposedly does this.
inline and emit in every TU
static inline void foo(void) { ... }
For all of these except the static
one, you can add a void foo(void)
declaration above. This helps with the "best practice" of writing clean headers, then #include
ing a separate file with the inline definitions. Then, if using C-style inlines, #define
some macro differently in one dedicated TU to provide the out-of-line definitions.
Don't forget extern "C"
if the header might be used from both C and C++!
There are also a couple of related things:
never inline
Add __attribute__((noinline))
to any declaration of the function.
MSVC has __declspec(noinline)
and [[msvc::noinline]]
but it is documented to only work for member functions. However, I've seen mention of "security attributes" which might prevent inlining?
force other functions to be inlined into this one if possible.
Add __attribute__((flatten))
to any declaration of the function.
Note that noinline
is more powerful than this (not tested on MSVC), as are functions whose definition isn't known at compile-time.
MSVC now documents [[msvc::flatten]]
; note that it applies to a scope rather than to a function. Formerly there was no equivalent, since [[msvc::forceinline_calls]]
is not recursive.
.h
and theextern inline
declaration in exactly one.c
to instantiate a non-inline definition and make a working C program with a non-static
inline
function defined in a header and thus able to actually inline, but still link if it doesn't. In C, should inline functions in headers be externed in the .c file? is also about that, with a concise answer. – Adamite