Use of 'extern' with inline

Inlining functions

C uses the inline keyword to suggest to the compiler that it should try to make this function inline with the calling function where ever it can.

The extern keyword

Defining a function as 'extern inline' has a slightly non-intuitive behaviour . It says "please attempt to inline this code, but if you can't then don't bother emitting any code for the function".

An example serves best

extern inline int fn(int i, int j) {
        printf("in fn()\n");
        return (i == j);
}
 
main(void)
{
        return fn(100,101);
}

compiling this without optimisation gives this

ianw@tartufi:~$ gcc -o test test.c
/tmp/ccyIp8CB.o(.text+0x22): In function `main':
: undefined reference to `fn'
collect2: ld returned 1 exit status

What has happened is that without optimisation gcc does not inline any code. Thus it has emitted a symbol for fn which it can not resolve! Removing the extern allows the file to compile fine, because the asm for the function is still emitted. Adding -O1 to the gcc command also compiles, because now optimisation is on, inlining is done and the function call gets replaced by the inline code.

Andi Klein added in LKML post

How to use extern inline

The best way to use extern inline is to define the function you want inlined as usual without the inline specifier. Then, when you write the function definition for the function add the 'extern inline' before it.

This is handy if you have what ammounts to a library file in your project -- declare all your functions in here as usual and in the headers define them as extern inline. This way gcc will try to inline, but if it fails will fall back to the real function (or if you compile without optimisation).

extern inline fn(int,int);
 
int fn(int i, int j) {
        printf("in fn()\n");
        return (i == j);
}
 
main(void)
{
        return fn(100,101);
}

This means the code for fn still gets emitted, but if optimistaion is turned on the code is inlined, if it's turned off the left over symbol will still resolve however. In essence you've written something as fast as a macro when optimised but with the added advantage of type checking.

static keyword

static inline lets the compiler try and be a little more clever with what it is doing -- since it knows the function is only referenced from within this file it can decide if it is appropriate to always inline the function, and thus not emit any code for it (or, conversely, emit code for the function if it can not always be inlined).

inline

inline by it's self always emits the code (incase some other function needs it) but inlines the function when possible. This is kind of useless -- if you know you only want to access the function from within your current file declare it as static so you at least have a chance of smaller code; otherwise just define it as normal and prototype it as extern inline.

IA64wiki: externinline (last edited 2009-12-10 03:14:05 by localhost)

Gelato@UNSW is sponsored by
the University of New South Wales National ICT Australia The Gelato Federation Hewlett-Packard Company Australian Research Council
Please contact us with any questions or comments.