Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use of the `inline` keyword in C?

Tags:

c

inline

c99

People also ask

Why inline is used?

Inline functions are commonly used when the function definitions are small, and the functions are called several times in a program. Using inline functions saves time to transfer the control of the program from the calling function to the definition of the called function.

Is inline available in C?

Standard support. C++ and C99, but not its predecessors K&R C and C89, have support for inline functions, though with different semantics. In both cases, inline does not force inlining; the compiler is free to choose not to inline the function at all, or only in some cases.

What is __ inline in C?

The __inline keyword suggests to the compiler that it compiles a C or C++ function inline, if it is sensible to do so. The semantics of __inline are exactly the same as those of the inline keyword.

Is inline keyword useful?

Specifying inline (explicitly, or implicitly when writing member functions inside a class definition) encourages the compiler to do a better job.


A C code can be optimized in two ways: For Code size and for Execution Time.

inline functions:

gcc.gnu.org says,

By declaring a function inline, you can direct GCC to make calls to that function faster. One way GCC can achieve this is to integrate that function's code into the code for its callers. This makes execution faster by eliminating the function-call overhead; in addition, if any of the actual argument values are constant, their known values may permit simplifications at compile time so that not all of the inline function's code needs to be included. The effect on code size is less predictable; object code may be larger or smaller with function inlining, depending on the particular case.

So, it tells the compiler to build the function into the code where it is used with the intention of improving execution time.

If you declare Small functions like setting/clearing a flag or some bit toggle which are performed repeatedly, inline, it can make a big performance difference with respect to time, but at the cost of code size.


non-static inline and Static inline

Again referring to gcc.gnu.org,

When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.


extern inline?

Again, gcc.gnu.org, says it all:

If you specify both inline and 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.

This combination of inline and extern has almost the effect of a macro. The way to use it is to put a function definition in a header file with these keywords, and put another copy of the definition (lacking inline and extern) in a library file. The definition in the header file causes most calls to the function to be inlined. If any uses of the function remain, they refer to the single copy in the library.


To sum it up:

  1. For inline void f(void){}, inline definition is only valid in the current translation unit.
  2. For static inline void f(void) {} Since the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.
  3. For extern inline void f(void); Since the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.

Note: when I talk about .c files and .h files in this answer, I assume you have laid out your code correctly, i.e. .c files only include .h files. The distinction is that a .h file may be included in multiple translation units.

static inline void f(void) {} has no practical difference with static void f(void) {}.

In ISO C, this is correct. They are identical in behaviour (assuming you don't re-declare them differently in the same TU of course!) the only practical effect may be to cause the compiler to optimize differently.

inline void f(void) {} in C doesn't work as the C++ way. How does it work in C? What actually does extern inline void f(void); do?

This is explained by this answer and also this thread.

In ISO C and C++, you can freely use inline void f(void) {} in header files -- although for different reasons!

In ISO C, it does not provide an external definition at all. In ISO C++ it does provide an external definition; however C++ has an additional rule (which C doesn't), that if there are multiple external definitions of an inline function, then the compiler sorts it out and picks one of them.

extern inline void f(void); in a .c file in ISO C is meant to be paired with the use of inline void f(void) {} in header files. It causes the external definition of the function to be emitted in that translation unit. If you don't do this then there is no external definition, and so you may get a link error (it is unspecified whether any particular call of f links to the external definition or not).

In other words, in ISO C you can manually select where the external definition goes; or suppress external definition entirely by using static inline everywhere; but in ISO C++ the compiler chooses if and where an external definition would go.

In GNU C, things are different (more on this below).

To complicate things further, GNU C++ allows you to write static inline an extern inline in C++ code... I wouldn't like to guess on what that does exactly

I never really found a use of the inline keyword in my C programs, and when I see this keyword in other people's code, it's almost always static inline

Many coders don't know what they're doing and just put together something that appears to work. Another factor here is that the code you're looking at might have been written for GNU C, not ISO C.

In GNU C, plain inline behaves differently to ISO C. It actually emits an externally visible definition, so having a .h file with a plain inline function included from two translation units causes undefined behaviour.

So if the coder wants to supply the inline optimization hint in GNU C, then static inline is required. Since static inline works in both ISO C and GNU C, it's natural that people ended up settling for that and seeing that it appeared to work without giving errors.

, in which I see no difference with just static.

The difference is just in the intent to provide a speed-over-size optimization hint to the compiler. With modern compilers this is superfluous.


From 6.7.4 Function specifiers in C11 specs

6 A function declared with an inline function specifier is an inline function. Making a function an inline function suggests that calls to the function be as fast as possible.138)The extent to which such suggestions are effective is implementation-defined.139)

138) By using, for example, an alternative to the usual function call mechanism, such as inline substitution. Inline substitution is not textual substitution, nor does it create a new function. Therefore, for example, the expansion of a macro used within the body of the function uses the definition it had at the point the function body appears, and not where the function is called; and identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a single address, regardless of the number of inline definitions that occur in addition to the external definition.

139) For example, an implementation might never perform inline substitution, or might only perform inline substitutions to calls in the scope of an inline declaration.

It suggests compiler that this function is widely used and requests to prefer speed in invocation of this function. But with modern intelligent compiler this may be more or less irrelevant as compilers can decide whether a function should be inlined and may ignore the inline request from users, because modern compilers can very effectively decide about how to invoke the functions.

static inline void f(void) {} has no practical difference with static void f(void) {}.

So yes with modern compilers most of the time none. With any compilers there are no practical / observable output differences.

inline void f(void) {} in C doesn't work as the C++ way. How does it work in C?

A function that is inline anywhere must be inline everywhere in C++ and linker does not complain multiple definition error (definition must be same).

What actually does extern inline void f(void); do?

This will provide external linkage to f. Because the f may be present in other compilation unit, a compiler may choose different call mechanism to speed up the calls or may ignore the inline completely.


A function where all the declarations (including the definition) mention inline and never extern.
There must be a definition in the same translation unit. The standard refers to this as an inline definition.
No stand-alone object code is emitted, so this definition can't be called from another translation unit.

In this example, all the declarations and definitions use inline but not extern:

// a declaration mentioning inline     
inline int max(int a, int b);

// a definition mentioning inline  
inline int max(int a, int b) {  
  return a > b ? a : b;  
}

Here is a reference which can give you more clarity on the inline functions in C & also on the usage of inline & extern.