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?
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.
This is the gnu_inline
hiccup. Use -std=gnu99 -fgnu89-inline
.
For more information see Function Attributes (item gnu_inline
).
The relevant passage:
In C, if the function is neither extern nor static, then the function is compiled as a standalone function, as well as being inlined where possible.
This is how GCC traditionally handled functions declared inline. Since ISO C99 specifies a different semantics for inline, this function attribute is provided as a transition measure and as a useful feature in its own right. This attribute is available in GCC 4.1.3 and later. It is available if either of the preprocessor macros GNUC_GNU_INLINE or GNUC_STDC_INLINE are defined. See An Inline Function is As Fast As a Macro.
You should declare 'myfunc' before define it.
For example this code can be compiled with -std=gnu99 option:
#include <stdio.h>
int myfunc(int);
inline int myfunc (int x) {
return x+3;
}
int main () {
printf("%d", myfunc(2));
return 0;
}
UPDATED
Actually, regarding to the C standard inline keyword is just a suggestion to the C compiler. But compiler can choose not to inline. So it can do its own way, therefore.
In your example you can use function declaration as I showed above - or you can add optimization flag '-O3' (tested on linux gcc) and above - in this case your source code will compiled without extra-declaration.
UPDATED
Here you can find deeper explanation: https://blogs.oracle.com/dew/entry/c99_inline_function
Apparently you need to specify that you are using and you want to adopt inline functions
-fgnu89-inline
The option -fgnu89-inline tells GCC to use the traditional GNU semantics for "inline" functions when in C99 mode. This option is
accepted and ignored by GCC versions 4.1.3 up to but not including
4.3. In GCC versions 4.3 and later it changes the behavior of GCC in C99 mode. Using this option is roughly equivalent to adding the
"gnu_inline" function attribute to all inline functions.
The option -fno-gnu89-inline explicitly tells GCC to use the C99 semantics for "inline" when in C99 or gnu99 mode (i.e., it
specifies the default behavior). This option was first supported in
GCC 4.3. This option is not supported in C89 or gnu89 mode.
The preprocessor macros __GNUC_GNU_INLINE__
and __GNUC_STDC_INLINE__
may be used to check which semantics are in
effect for "inline" functions.
Source: http://linux.die.net/man/1/gcc
So to compile your code you need at least this:
gcc source.c -std=gnu99 -fgnu89-inline