72

I defined my function in .c (without header declaration) as here:

inline int func(int i) {
 return i+1;
}

Then in the same file below I use it:

...
i = func(i);

And during the linking I got "undefined reference to 'func'". Why?

2
  • 3
    Either make it static or provide a non-inline definition that the linker can find. Commented Apr 26, 2013 at 21:39
  • See also stackoverflow.com/questions/6312597 Commented Apr 26, 2013 at 21:44

3 Answers 3

80

The inline model in C99 is a bit different than most people think, and in particular different from the one used by C++

inline is only a hint such that the compiler doesn't complain about doubly defined symbols. It doesn't guarantee that a function is inlined, nor actually that a symbol is generated, if it is needed. To force the generation of a symbol you'd have to add a sort of instantiation after the inline definition:

int func(int i);

Usually you'd have the inline definition in a header file, that is then included in several .c files (compilation units). And you'd only have the above line in exactly one of the compilation units. You probably only see the problem that you have because you are not using optimization for your compiler run.

So, your use case of having the inline in the .c file doesn't make much sense, better just use static for that, even an additional inline doesn't buy you much.

Sign up to request clarification or add additional context in comments.

4 Comments

my bad, an extern file-scope declaration without inline does force the definition to not be an inline one
I got one question, why does this situation occur when optimization is turned off ? When I turn it on with gcc -O1 option it will just compile, what option in gcc optimization provide this code to be compiled in the proper way ?
@Lazureus, when you compile with -O0, I suppose that you mean that, gcc usually doesn't inline any function. So then you must have the symbols defined somewhere, otherwise it wouldn't find any of the inline declare-defined functions.
Is the prototype really needed after? I did some test that seems to confirm my believe that a prototype before the definition will also force the symbol generation. Just run and see: echo "int f(void); inline int f(void){return 42;}" | cc -x c -Wall -Wextra -Wpedantic -pedantic-errors -Werror -O3 -std=c99 -S - -o -. Is that an extension to the standard (or misinterpretation in gcc)?
50

C99 inline semantics are often misunderstood. The inline specifier serves two purposes:

First, as a compiler hint in case of static inline and extern inline declarations. Semantics remain unchanged if you remove the specifier.

Second, in case of raw inline (ie without static or extern) to provide an inline definition as an alternative to an external one, which has to be present in a different translation unit. Not providing the external one is undefined behaviour, which will normally manifest as linking failure.

This is particularly useful if you want to put a function into a shared library, but also make the function body available for optimization (eg inlining or specialization). Assuming a sufficiently smart compiler, this allows you to recover many of the benefits of C++ templates without having to jump through preprocessor hoops.

Note that it's a bit more messy than I described here as having another file scope non-inline external declaration will trigger the first case as described in Jens' answer, even if the definition itself is inline instead of extern inline. This is by design so you can have have a single inline definition in a header file, which you can include into the source file that provides the external one by adding a single line for the external declaration.

4 Comments

this answer is somewhat obsolete - I thought there was a mistake in Jens' one, but it turned out I was mistaken...
I read both of your answers, Jens' one first and reading yours helped my understanding even though Jens' is correct.
Actually, explaining when is thus semantic useful is a valuable answer (at least to me).
Confused with "inline definition as an alternative to an external one" - so when my code calls it, which "alternative" is called??
4

This is because of the way GCC handle inline function. GCC performs inline substitution as the part of optimization.

To remove this error use static before inline. Using static keyword force the compiler to inline this function, which makes the program compile successfully.

static inline int func(int i) {
 return i+1;
}
...
i = func(i);

3 Comments

But how to deal with member-functions?
@Piroxiljin: C doesn't have member functions, only C++ has that. According to the Jens' answer on this question, the meaning of inline differs between C and C++.
Huh. What's going on here? I always throught static and inline were orthogonal for some reason. As in, static implies it must be present, while inline (by definition) does not. (by "not present" I mean as a defined symbol, since it would have been inlined).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.