Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why was the C compiler unable to compile code with an inline function?

It looks extremely weird, but I was unable to compile following simple code:

inline void inline_func() {}
static inline void static_inline_func() {}

void some_func()
{
    // THERE IS A PROBLEM with "inline" function
    inline_func();

    // THERE IS NO PROBLEM with "static inline" function
    static_inline_func();
}

int main(int argc, char *argv[])
{
    some_func();
    return 0;
}

Compiler simply produces error:

$ gcc -Wall -o main main.c
/usr/bin/ld: /tmp/ccs7lKMm.o: in function `some_func':
main.c:(.text+0x15): undefined reference to `inline_func'
collect2: error: ld returned 1 exit status

I tried this code also with Clang compiler and got similar problem.

Edit

I don't think this question is a duplicate. It isn't a question about the difference between inline and static inline. This question is about the reason why an inline function cannot be compiled by some compilers while it is compiled by others (see comments).

Edit

This code can be compiled without errors using the -Os optimization argument:

$ gcc -Wall -Os -o main main.c
like image 392
lol lol Avatar asked Oct 27 '25 14:10

lol lol


2 Answers

why an inline function cannot be compiled by some compilers

Inline is magic. When you use inline (without extern or static), you are required by the C programming language specification to provide two definitions of the function - one inline definition that you provided, and the other external definition of the same function. Compiler is free to choose either function - the inline or external version of it.

The inline function code you posted cannot be compiled by some compilers, because some compilers choose to use the external definition of the function. You did not provide it. Because you failed to adhere to the rules of C programming in the standard by breaking the requirement of providing two definitions of the function, your code is invalid. You have to provide the external definition of the inline functions, for example by compiling a separate file and linking with it.

Because today's compilers when compared to 30 years ago are ridiculously fast, sole inline is rather archaic and doesn't make much sense. Use static when you want your function to be inlined. Compiler will inline function no matter if you use inline or not, and he will do better decisions which functions to inline than you. (I use inline in static inline to silence compiler warnings about unused functions in gcc).

From https://en.cppreference.com/w/c/language/inline :

If a function is declared inline in some translation units, it does not need to be declared inline everywhere: at most one translation unit may also provide a regular, non-inline non-static function, or a function declared extern inline. This one translation unit is said to provide the external definition. In order to avoid undefined behavior, one external definition must exist in the program if the name of the function with external linkage is used in an expression, see one definition rule.

like image 107
KamilCuk Avatar answered Oct 29 '25 05:10

KamilCuk


This is completely normal and correct behavior. See Is "inline" without "static" or "extern" ever useful in C99? for an explanation of what happens if you define a function as inline.

Roughly speaking, you have told the compiler that if it wishes to inline the function inline_func(), you have provided it the code with which to do so. This definition is only used for inlining, and does not by itself cause a standalone copy (or "external definition" in the language of the C standard) of the function to be emitted.

And the compiler is not required to actually inline the function where it is called; it may instead emit a call instruction. If so, then there has to be a standalone copy of the function somewhere in the program.

gcc and clang, when compiling without optimizations, will never inline a function call (unless it is declared with the non-portable always_inline attribute). It tries instead to emit a call to the standalone function, which as mentioned above, does not exist in your program. If you enable optimizations (-O) you will find that the program compiles and links successfully. (Though in other cases, even with optimization enabled, the compiler may still choose not to inline some functions, if it thinks it is not an overall gain for performance.)

The C standard allows both behaviors. C17 6.7.4p7 says "It is unspecified whether a call to the function uses the inline definition or the external definition."

To get the program to work reliably, you can add the line

extern inline void inline_func(void);

which tells the compiler to emit a standalone copy of the function, using the same definition given above with plain inline. Then even if the compiler chooses not to inline the function call, there will exist a standalone copy that it can successfully call. Try on godbolt.

like image 39
Nate Eldredge Avatar answered Oct 29 '25 04:10

Nate Eldredge



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!