In ISO C99 and ISO C11, having in the header file:
inline void f(void) { ..... }
means that the compiler can indeed choose between inlining the function, or treating it as a regular function.
However, when treating as a regular function, the compiler will behave similarly to if you had written void f(void);
, i.e. it will expect to link to a body of f
elsewhere.
So you need to put in exactly one of your translation units the line:
extern inline void f(void);
which causes the compiler to emit the body in that unit.
However, in GNU C, using inline void f(void) { ... }
leads to undefined behaviour. The compiler can still choose, but when it chooses to treat as a regular function, it behaves as if you had written void f(void) { ... }
, i.e. it emits the function body in every translation unit that uses it.
Some people write their functions in the header as static inline void f(void) { .... }
, which works in both ISO C and GNU C, but possibly makes it harder for the linker to combine all of the copies into one.
See this thread for more detail