Linkage of inline functions
Beginning of C only.
In C, inline functions are treated by default as having static linkage;
that is, they are only visible within a single translation unit. Therefore,
in the following example, even though function
foo
is
defined in exactly the same way, foo
in file A
and foo
in
file B
are treated as separate functions: two function
bodies are generated, and assigned two different addresses in memory: // File A
#include <stdio.h>
__inline__ int foo(){
return 3;
}
void g() {
printf("foo called from g: return value = %d, address = %#p\n", foo(), &foo);
}
// File B
#include <stdio.h>
__inline__ int foo(){
return 3;
}
void g();
int main() {
printf("foo called from main: return value = %d, address = %#p\n", foo(), &foo);
g();
}
The output from the compiled program is: foo called from main: return value = 3, address = A100000000000000D8ED5D51EA000B68
foo called from g: return value = 3, address = A100000000000000D8ED5D51EA000B58
Since
inline functions are treated as having internal linkage, an inline
function definition can co-exist with a regular, external definition
of a function with the same name in another translation unit. However,
when you call the function from the file containing the inline definition,
the compiler may choose either the inline version defined in
the same file or the external version defined in another file
for the call; your program should not rely on the inline version being
called. In the following example, the call to
foo
from
function g
could return either 6 or 3: // File A
#include <stdio.h>
__inline__ int foo(){
return 6;
}
void g() {
printf("foo called from g: return value = %d\n", foo());
}
// File B
#include <stdio.h>
int foo(){
return 3;
}
void g();
int main() {
printf("foo called from main: return value = %d\n", foo());
g();
}
Similarly, if you define a function as extern
inline
, or redeclare an inline
function
as extern
, the function simply becomes a regular,
external function and is not inlined. End of C only.
Beginning of C++ only.
You must define an inline function in exactly the same
way in each translation unit in which the function is used or called.
Furthermore, if a function is defined as inline
,
but never used or called within the same translation unit, it is discarded
by the compiler.
Nevertheless, in C++, inline functions are
treated by default as having external linkage, meaning that
the program behaves as if there is only one copy of the function. The
function will have the same address in all translation units and each
translation unit will share any static locals and string literals. Therefore,
compiling the previous example gives the following output:
foo called from main: return value = 3, address = A100000000000000D8ED5D51EA000B58
foo called from g: return value = 3, address = A100000000000000D8ED5D51EA000B68
Redefining
an inline function with the same name but with a different function
body is illegal; however, the compiler does not flag this as an error,
but simply generates a function body for the version defined in the
first file entered on the compilation command line, and discards the
others. Therefore, the following example, in which inline function foo
is
defined differently in two different files, may not produce the expected
results: // File A
#include <stdio.h>
inline int foo(){
return 6;
}
void g() {
printf("foo called from g: return value = %d, address = %#p\n", foo(), &foo);
}
// File B
#include <stdio.h>
inline int foo(){
return 3;
}
void g();
int main() {
printf("foo called from main: return value = %d, address = %#p\n", foo(), &foo);
g();
}
When file A and file B are bound into a single ILE program,
the output is: foo called from main: return value = 6, address = A100000000000000F3551B782F000B38
foo called from g: return value = 6, address = A100000000000000F3551B782F000B38
The
call to foo
from main
does not use
the inline definition provided in file B, but rather calls foo
as
a regular external function defined in file A. It is your responsibility
to ensure that inline function definitions with the same name match
exactly across translation units, to avoid unexpected results.Because
inline functions are treated as having external linkage, any static
local variables or string literals that are defined within the body
of an inline function are treated as the same object across translation
units. The following example demonstrates this:
// File A
#include <stdio.h>
inline int foo(){
static int x = 23;
printf("address of x = %#p\n", &x);
x++;
return x;
}
void g() {
printf("foo called from g: return value = %d\n", foo());
}
// File B
#include <stdio.h>
inline int foo()
{
static int x=23;
printf("address of x = %#p\n", &x);
x++;
return x;
}
void g();
int main() {
printf("foo called from main: return value = %d\n", foo());
g();
}
The output of this program shows that x
in
both definitions of foo is indeed the same object: address of x = A100000000000000F3551B782F000B38
foo called from main: return value = 24
address of x = A100000000000000F3551B782F000B38
foo called from g: return value = 25
If you want
to ensure that each instance of function defined as inline is treated
as a separate function, you can use the static
specifier
in the function definition in each translation unit. Note, however,
that static inline functions are removed from name lookup during template
instantiation, and are not found.
Related information
End of C++ only.