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
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
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.
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
#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;
}
#endifCompilers 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.