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?
The compiler can identify when a symbol isn't declared, but it can't tell when the symbol isn't defined. That's because the definition may be in a different source file or library. If a symbol is referred to but never defined, the linker generates an unresolved external symbol error.
Unresolved external references occur when the symbol for a function or global variable is referenced in a program, but none of the object files or libraries specified in the link step contain a definition for that symbol.
So when we try to assign it a value in the main function, the linker doesn't find the symbol and may result in an “unresolved external symbol” or “undefined reference”. The way to fix this error is to explicitly scope the variable using '::' outside the main before using it.
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.
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.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With