Just for info. Here are some notes I collected about 'inline' three months ago. If it's too much details, skip the text until "Results" at the bottom :-)
------------------------------------------------------------------------------- Use of 'inline' in function definitions ======================================= Standards: * ANSI/ISO C++ 3.2.(3) An inline function shall be defined in every transla- tion unit in which it is used. 7.1.2.(2) A function declaration (_dcl.fct_, _class.mfct_, _class.friend_) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the func- tion body at the point of call is to be preferred to the usual func- tion call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by _dcl.fct.spec_ shall still be respected. 7.1.2.(3) footnote The inline keyword has no effect on the linkage of a function. 7.1.2.(4) An inline function shall be defined in every translation unit in which it is used and shall have exactly the same definition in every case (_basic.def.odr_). [Note: a call to the inline function may be encountered before its definition appears in the translation unit. ] If a function with external linkage is declared inline in one transla- tion unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. An inline function with external linkage shall have the same address in all translation units. [Note: a static local variable in an extern inline function always refers to the same object. ] * ISO C99 6.2.2.(5) If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. [Note: This applies to function declarations only, not to function definitions!] 6.7.4.(3) An inline definition of a function with external linkage shall not contain a definition of a modifiable object with static storage duration, and shall not contain a reference to an identifier with internal linkage. [I.e. what is explicitly allowed in C++ is forbidden in C.] 6.7.4.(5) A function declared with an inline function specifier is an inline function. The function specifier may appear more than once; the behavior is the same as if it appeared only once. Making a function an inline function suggests that calls to the function be as fast as possible. The extent to which such suggestions are effective is implementation- defined. 6.7.4.(6) 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. 6.7.4.(6) footnote Since an inline definition is distinct from the corresponding external definition and from any other corresponding inline definitions in other translation units, all corresponding objects with static storage duration are also distinct in each of the definitions. 6.9.(5) An "external definition" is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one. 6.9.(5) footnote Thus, if an identifier declared with external linkage is not used in an expression, there need be no external definition for it. Summary: * In C++, "static inline" is semantically equivalent to "static"; "inline" and "extern inline" both designate the same definition in every compilation unit. The effects are very similar. The difference is that when using "inline" without "static", all instantiations of the function are identical (have the same address), and it is available through a simple "extern" declaration. * In C99, "static inline" is semantically equivalent to "static"; "extern inline" is semantically equivalent to "extern" (in particular, multiple-definition errors can occur). "inline" without extern is a semantic nop, only a optimization hint for the compiler. gcc-2.7.2.3 manual: Note that in C and Objective C, unlike C++, the @code{inline} keyword does not affect the linkage of the function. If you specify both @code{inline} and @code{extern} in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it. gcc-2.95.3 manual: Likewise. gcc-4.2-... manual: Inline functions are included in the ISO C99 standard, but there are currently substantial differences between what GCC implements and what the ISO C99 standard requires. Test case: =========================== foo1.c =========================== extern inline int plus (int a, int b) { return a+b; } int main () { return plus (-2, 2); } =========================== foo2.c =========================== extern inline int plus (int a, int b) { return a+b; } int foo (int x) { return plus(x, 42); } =========================== foo3.c =========================== extern inline int plus (int a, int b) { return a+b; } int (*f3) (int, int) = plus; =========================== foo4.c =========================== extern int plus (int a, int b); int (*f4) (int, int) = plus; ============================================================== * extern inline inline static inline static without a body is an error in C++ (Sun C++ error for foo4). * extern inline: with Sun C++: foo1, foo2 inlined; foo3 plus defined as extern (uses segment with LINK_ONCE_DISCARD -> no multiple definition errors); foo4 plus undefined (can lead to undefined reference error). with g++ 2.95.3 ... 4.2 unoptimizing: foo1, foo2, foo3 defined as extern (weak -> no multiple definition errors); foo4 plus undefined (cannot lead to undefined reference error). with g++ 2.95.3 ... 4.2 optimizing: foo1, foo2 inlined; foo3 defined as extern (weak -> no multiple definition errors); foo4 plus undefined (can lead to undefined reference error). with Sun C99: foo1, foo2, foo3 plus defined as extern (uses segment with LINK_ONCE_DISCARD -> no multiple definition errors); foo4 plus undefined (cannot lead to undefined reference error). with gcc 2.95.3 ... 4.2 unoptimizing: foo1, foo2, foo3, foo4 plus undefined (can lead to undefined reference error). with gcc 2.95.3 ... 4.2 optimizing: foo1, foo2 inlined; foo3, foo4 plus undefined (can lead to undefined reference error). * inline: with Sun C++: foo1, foo2 inlined; foo3 plus defined as extern (uses segment with LINK_ONCE_DISCARD -> no multiple definition errors); foo4 plus undefined (can lead to undefined reference error). with g++ 2.95.3 ... 4.2 unoptimizing: foo1, foo2, foo3 defined as extern (weak -> no multiple definition errors); foo4 plus undefined (cannot lead to undefined reference error). with g++ 2.95.3 ... 4.2 optimizing: foo1, foo2 inlined; foo3 defined as extern (weak -> no multiple definition errors); foo4 plus undefined (can lead to undefined reference error). with Sun C99: foo1, foo2, foo3, foo4 plus undefined (can lead to undefined reference error). with gcc 2.95.3 ... 4.2: foo1, foo2, foo3 plus defined as extern (can lead to multiple definition errors). foo4 plus undefined (cannot lead to undefined reference error). * static inline: with Sun C++: foo1, foo2 inlined; foo3 plus defined as static; foo4 plus undefined (will lead to undefined reference error). with g++ 2.95.3 ... 4.2, with Sun C99, with gcc 2.95.3 ... 4.2: foo1, foo2, foo3 plus defined as static; foo4 plus undefined (will lead to undefined reference error). Compiler Bugs: - No bug in C++ mode. - gcc violates 6.7.4.(6), Sun C gets it right. This is listed in http://gcc.gnu.org/c99status.html. Results: * "static inline" is safe to use and has the same semantics in C and in C++: it never leads to a globally defined symbol and never leads to an undefined symbol. * Use of "extern" to refer to functions defined with "inline" or "extern inline" is unreliable. (In C++, because of ISO C++ 7.1.2.(4). In C for references to "inline" functions, because of ISO C 6.7.4.(6). In C for references to "extern inline" functions, because gcc is buggy.) * The semantics of "may create a globally defined symbol, but avoid multiple-definition errors, assuming all definitions are equivalent" can be gotten - in C++ through "inline" or "extern inline" (both equivalent, portable), - with Sun C through "extern inline", - with GCC through "inline". * The semantics of "assume a definition in a different compilation unit" can be gotten - portably through "extern", - with Sun C through "inline", - with GCC through "extern inline". * The way to provide a function definition that has external linkage and is inlinable: - In C++, you _must_ put it into the .h file. "inline" or "extern inline" are both usable. "extern" declarations in compilation units that don't use the .h file are forbidden. - In C99, an "inline" definition goes into the .h file; an "extern" or "extern inline" definition must be present in exactly one compilation unit (and it may include the .h file). "extern" declarations in compilation units that don't use the .h file are possible. There are three ways to emit a definition with external linkage with gcc: 1) inline int plus (int a, int b) { return a+b; } 2) extern inline int plus (int a, int b) { return a+b; } inline int plus (int a, int b) { return a+b; } 3) extern inline int plus (int a, int b) { return a+b; } extern int plus (int a, int b) { return a+b; } [Note that in cases 2, 3, the opposite order of definitions gives an error!] Which compilers don't yet support inline? Solaris 7 cc lacks inline entirely HP-UX 11 cc has an unusable inline (return type must not be a typedef) IRIX 6 cc has __inline but does not understand extern __inline. AIX 4 xlc has __inline, uses the C99 semantics OSF/1 5.1 cc has inline, uses the C99 semantics