The following code:
#include <stdio.h>
inline int myfunc (int x) {
return x+3;
}
int main () {
printf("%d", myfunc(2));
return 0;
}
does not compile when I use the -std=gnu99
flag (I am compiling with gcc). This is the error it throws:
gcc -std=gnu99 -c main.c -o main.o
gcc -std=gnu99 main.o -o main
main.o: In function `main':
main.c:(.text+0x15): undefined reference to `myfunc'
collect2: ld returned 1 exit status
make: *** [main] Error 1
The compilation goes with no problems when -std=gnu99
is omitted. Does anyone know why is the linker complaining if -std=gnu99
is used?
Remember, inlining is only a request to the compiler, not a command. Compiler can ignore the request for inlining. Compiler may not perform inlining in such circumstances like: If a function contains a loop.
All those functions that contain a loop statement (for loop, while loop, or do-while loop) can not be considered as an inline function by the compiler. The compiler will not consider a function to be an inline function if it is recursive.
The compiler can't inline a function if: The function or its caller is compiled with /Ob0 (the default option for debug builds). The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other). The function has a variable argument list.
Whether something is inline or not is part of code generation. That's the compiler's job. Ergo, inlining is done at compile time.
In C99 you need to specify either a declaration to your inline function like
int myfunc(int);
or allow the compiler to actually inline the function by specifying -finline-functions
or -O3
.
Quoting the C99 standard:
Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.
So the compiler is free to use the external definition of myfunc
- which doesn't exist if you don't provide it, hence the linker error. Why does it prefer to choose a non existing external definition? Because you disallowed inlining by not using -finline-functions
or a optimization level which contains this flag.
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