C, built-in function and GCC

If I have:

inline int foo(void) { return 10 + 3; } int main(void) { foo(); } 

with GCC, the file compiles, but the linker returns an undefined reference to foo

Instead, if I remove inline , the linker will be happy!

The ID of the external definition seems to be visible to the linker, but the ID of the inline definition is not.

Also, if I compile the -O3 flag, the linker sees the identifier of the inline definition.

What is the problem?

+7
c
source share
4 answers

Ok, so after reading the VivienG link , I think I understood the exact reasoning for this error message. This is confusing and misleading (at least for me this should not happen if you have only one translation unit), but you can explain:

  • Assuming that the compiler does not really want to embed the code, he should know where to put it, especially when it is used in several translation units.

  • The classic approach is to create multiple copies, one for each translation unit (or at least for those units where it was used).

  • This can cause problems, for example. while trying to do some comparisons of function pointers (the question still remains why you should do this).

To counter this (and other issues that I might not have listed here), they thought of some pretty neat (although, as I mentioned, deceptive) solution:

You declare the function as inline as 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 would save your as-is function and put it in the header file (so that it knows where it will be used):

 inline int foo(void) { return 10 + 3; } 

In addition, in order to tell the compiler where to place the non-linear version, you need to add one more forward declaration to one translation unit:

 extern inline int foo(void); 

Thus, the whole concept changes significantly compared to the classic functions: put the implementation in the header, and then a short declaration in only one file.

As already mentioned, when using the -O3 option, all code marked with inline is actually embedded, which will not cause a problem.

+4
source share

You need to pass -std=gnu11 your compiler.

gcc main. -o main -std = gnu11

EDIT: post answer many questions.

+2
source share

In the C language of C99, if you want the built-in function to be used in only one compilation unit, you must declare it as a "static built-in", and everything will be fine. Otherwise, a built-in function declared without "static" must be declared as "extern inline" in exactly one compilation unit.

Usually you either use the "static inline" in the .c file, or use the "inline" in the .h file and declare the "extern inline" function in exactly one .c file.

+1
source share

I think user3629249 comment hit the nail on the head. If you compile the code with -O3 , the call to foo() will be deleted. i.e. layout difference:

C- -O3 :

 main: .LFB4: .cfi_startproc xorl %eax, %eax ret .cfi_endproc 

Without -O3 :

 main: .LFB1: // ... call foo // ... 

Standard C says in footnote 161 (§6.9 / 5):

Thus, if an identifier declared with an external link is not used in the expression, there should be no external definition for this.

A function in the file area has an external link, but a function declared in a string without the extern keyword is a built-in definition. §6.9 / 5 states:

An external definition is an external declaration, which is also the definition of a function ( other than the built-in definition ), or an object. If an identifier declared with an external link is used in the expression (except as part of the operand sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there should be only one external definition for the identifier; otherwise there should be no more than one. 161)

4 [...] As discussed in 6.7, a definition that also forces you to reserve storage for an object or function called an identifier is a definition.

ie, using static or extern storage class specifiers.

+1
source share

All Articles