CInline Functions

Inline Functions

The inline keyword, added in C99, is a hint to the compiler that a function is a good candidate to have its body substituted directly at each call site, rather than being called through a normal function call. Done well, this removes call overhead (pushing a stack frame, jumping, returning) for small, frequently called functions like simple getters or one-line math helpers.

Basic syntax

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

Conceptually this looks identical to C++, but C's rules for how inline actually behaves across multiple files are meaningfully different, and this difference is a very common source of linker errors for people coming from C++.

C's inline semantics vs C++'s

In C, a plain inline function definition (without static or extern) is treated as an inline definition: it tells the compiler "you may inline calls to this function within this file," but it does not, by itself, guarantee that an ordinary, callable version of the function exists anywhere in the final program. If some other file calls the function in a way the compiler can't inline (for example, by taking its address, or if inlining is simply not performed), and no file provides an extern copy of the definition, you can get a linker error like undefined reference to the function — even though you clearly wrote a body for it.

math_utils.h

C
inline int square(int x) {
    return x * x;
}
/* In strict C99/C11, this header alone does not guarantee square()
   is linkable from every translation unit that includes it. */

The traditional fix under the C99 model is to provide exactly one external definition in a single .c file, using extern inline, alongside the inline version in the header. This works, but it's easy to get subtly wrong and confuses almost everyone the first time they encounter it.

A common point of confusion
C++'s `inline` was designed from the start to solve the "define a function in a header, include it everywhere" problem — an inline function in C++ is automatically given the special linkage needed for that to just work. C's `inline`, inherited from an older, more conservative model, was not designed with that goal primarily in mind, which is exactly why the two languages' rules diverge here despite looking like the same keyword.
The simplest safe pattern: static inline

In practice, the overwhelmingly common and safe pattern is to combine inline with static. A static inline function has internal linkage — each file that includes the header gets its own private copy — so there's never a question of which file provides the one "real" external definition, and you can put the function directly in a header with no extra ceremony:

math_utils.h

C
#ifndef MATH_UTILS_H
#define MATH_UTILS_H

static inline int square(int x) {
    return x * x;
}

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

#endif
Recommendation
Unless you have a specific, well-understood reason to want a single shared external definition across your whole program, reach for `static inline` in headers. It sidesteps the C99 external-linkage rules entirely and behaves the way most people intuitively expect an "inline header function" to behave.
Compilers often inline automatically anyway

Modern optimizing compilers (GCC, Clang, MSVC) perform their own inlining analysis based on function size, call frequency, and optimization level (-O2, -O3), completely independent of whether you wrote the inline keyword. A small static helper function defined in the same file as its caller is very likely to be inlined automatically at a reasonable optimization level, with or without the keyword.

inline is a hint, not a command
Just like `register`, the `inline` keyword does not force the compiler to actually inline the function — the compiler is always free to ignore the hint (for example, if the function is too large, or recursive), and it's equally free to inline functions you never marked `inline` at all if its own heuristics decide that's worthwhile. Treat `inline` purely as a suggestion, not a guarantee about the generated machine code.