If I have:
inline int foo(void)
{
return 10 + 3;
}
int main(void)
{
foo();
}
with GCC the file compiles well but the linker returns undefined reference to foo
Instead if I remove inline
the linker is happy!
It seems as an identifier of an external definition is visible to the linker but an identifier of an inline definition is not.
Also if I compile with -O3
flag the linker sees the identifier of the inline definition.
What's the problem?
Okay, so after reading through VivienG's link, I think I've understood the exact reasoning behind this error message. It's confusing and misleading (at least to me; it shouldn't happen if you've got just one translation unit), yet it is possible to explain:
Assuming the compiler doesn't want to actually inline the code, it has to know where to put that function, especially when it's used in multiple translation units.
Classic approach is to create multiple copies, one for each translation unit (or at least for those units where it's used).
This may cause problems, e.g. when trying to do some function pointer comparisons (still leaves the question why you'd to that though).
To counter this (and other issues I possibly didn't list here), they've thought of some actually quite neat (although - as mentioned - in my opinion misleading) solution:
You declare the function as inline
the way you know, but at the same time you tell the compiler where to put the non-inline version with the extern
keyword.
So in your example, you'd keep your function as-is and put it in a header file (so it's known where it's going to be used):
inline int foo(void)
{
return 10 + 3;
}
In addition, to tell the compiler where to place the non-inlined version, you'll have to add one more "forward" declaration in one translation unit:
extern inline int foo(void);
So the whole concept is essentially reversed when compared to classic functions: Put the implementation in the header and then a short declaration in just one file.
As mentioned already, while using the -O3
parameter, all code marked with inline
is actually inlined, which won't cause the issue to happen.
You need to pass -std=gnu11
to your compiler.
gcc main. -o main -std=gnu11
EDIT: This post answer lots of questions.
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