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

CInlineC99

C Problem Overview


I read several questions in stackoverflow about inline in C but still am not clear about it.

  1. static inline void f(void) {} has no practical difference with static void f(void) {}.
  2. inline void f(void) {} in C doesn't work as the C++ way. How does it work in C?
  3. What actually does extern inline void f(void); do?

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, in which I see no difference with just static.

C Solutions


Solution 1 - C

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.

Solution 2 - C

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.

Solution 3 - C

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.

Solution 4 - C

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.

Solution 5 - C

As a word "Inline" say "In" "Line", adding this keyword to function affects the program in runtime , when a program is compiled ,the code written insides function is pasted under the function call , as function calls are more costly than inline code, so this optimizes the code. So, static inline void f(void) {} and static void f(void) {} , in this inline keyword do makes difference in runtime. But when function has too many lines of code then it won't effect runtime. If you add static before function , function's life time is the life time of the whole program. And that function use is restricted to that file only. To know about extern you can refer to - https://stackoverflow.com/questions/856636/effects-of-the-extern-keyword-on-c-functions

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3810155View Question on Stackoverflow
Solution 1 - CWedaPashiView Answer on Stackoverflow
Solution 2 - CM.MView Answer on Stackoverflow
Solution 3 - CMohit JainView Answer on Stackoverflow
Solution 4 - CAlekhya VemavarapuView Answer on Stackoverflow
Solution 5 - Cuser3805321View Answer on Stackoverflow