Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C, inline function and GCC [duplicate]

Tags:

c

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?

like image 920
xdevel2000 Avatar asked Oct 22 '14 08:10

xdevel2000


Video Answer


2 Answers

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.

like image 105
Mario Avatar answered Oct 05 '22 02:10

Mario


You need to pass -std=gnu11 to your compiler.

gcc main. -o main -std=gnu11

EDIT: This post answer lots of questions.

like image 39
VivienG Avatar answered Oct 05 '22 02:10

VivienG